diff --git a/server/db/database.js b/server/db/database.js index d38abb2..a0dbeed 100644 --- a/server/db/database.js +++ b/server/db/database.js @@ -144,7 +144,7 @@ export default class DBAdapter { } } - async deleteOrdersByIds(orderIds) { + async clearOrders(orderIds) { if (!orderIds || orderIds.length === 0) { console.log("No orders to delete"); return; @@ -165,4 +165,199 @@ export default class DBAdapter { return Promise.reject(); } } + + async changeOrderInfo({ id, customer_name, orderDate }){ + if (!id) { + return Promise.reject({ + type: DB_USER_ERROR, + error: new Error("Order ID is required") + }); + } + + const currentDate = await getCurrentDate(); + if (orderDate < currentDate) { + return Promise.reject({ + type: DB_USER_ERROR, + error: new Error("Order date cannot be less than current date") + }); + } + + try { + const order = await this.#dbClient.query('SELECT * FROM orders WHERE id = ?', [id]); + + if (!order){ + return Promise.reject({ + type: DB_USER_ERROR, + error: new Error("Order not found") + }); + } + + const updatedName = customer_name; + const updatedDate = orderDate; + + await this.#dbClient.query('UPDATE orders SET customer_name = ?, order_date = ? WHERE id = ?', + [updatedName, updatedDate, id] + ); + + } catch(err){ + return Promise.reject({ + type: DB_INTERNAL_ERROR, + error: new Error("Server error") + }); + } + } + + async deleteOrderById(order_id){ + try { + const orderItems = await this.#dbClient.query( + `SELECT product_id, quantity FROM order_items WHERE order_id = ?`, + [order_id] + ); + + for (const item of orderItems){ + await this.#dbClient.query('UPDATE products SET quantity = quantity + ? WHERE id = ?', + [item.quantity, item.product_id] + ); + } + await this.#dbClient.query( + `DELETE FROM orders WHERE id = ?`, + [order_id] + ); + } catch(err){ + return Promise.reject({ + type: DB_INTERNAL_ERROR, + error: new Error("Server error") + }); + } + } + + async addOrderItem({ orderId, productId, quantity }){ + await this.#dbClient.query('BEGIN'); + try { + const product = await this.#dbClient.query( + 'SELECT quantity FROM products WHERE id = ?', [productId] + ); + + // TODO + if (!product || product.quantity < quantity){ + return Promise.reject(); + } + + const result = await this.#dbClient.query( + 'INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)', + [orderId, productId, quantity] + ); + + await this.#dbClient.query( + 'UPDATE products SET quantity = quantity - ? WHERE id = >', + [quantity, productId] + ); + + await this.#dbClient.query('COMMIT'); + } catch (err){ + await this.#dbClient.query('ROLLBACK'); + return Promise.reject(); + } + } + + async updateOrderItem({ itemId, quantity }){ + await this.#dbClient.query('BEGIN'); + try { + const item = await this.#dbClient.query( + 'SELECT product_id, quantity FROM order_items WHERE id = ?', [itemId] + ); + + // TODO + if (!item){ + return Promise.reject(); + } + + const diff = quantity - item.quantity; + + if (diff > 0){ + const product = await this.#dbClient.query( + 'SELECT quantity FROM products WHERE id = ?', [item.productId] + ); + + if (product.quantity < diff){ + return Promise.reject(); + } + + await this.#dbClient.query( + 'UPDATE products SET quantity = quantity - ? WHERE id = >', + [diff, item.productId] + ); + } + + if (diff < 0) { + await this.#dbClient.query( + 'UPDATE products SET quantity = quantity - ? WHERE id = >', + [-diff, item.productId] + ); + } + + await this.#dbClient.query( + 'UPDATE order_items SET quantity = ? WHERE id = >', + [quantity, itemId] + ); + + await this.#dbClient.query('COMMIT'); + } catch (err){ + await this.#dbClient.query('ROLLBACK'); + return Promise.reject(); + } + } + + async deleteOrderItem(itemId){ + await this.#dbClient.query('BEGIN'); + try { + const item = await this.#dbClient.query( + 'SELECT product_id, quantity FROM order_items WHERE id = ?', [itemId] + ); + + // TODO + if (!item){ + return Promise.reject(); + } + + await this.#dbClient.query( + 'UPDATE products SET quantity = quantity + ? WHERE id = >', + [item.quantity, item.productId] + ); + + await this.#dbClient.query( + 'DELETE FROM order_items WHERE id = ?', + [itemId] + ); + + await this.#dbClient.query('COMMIT'); + } catch (err){ + await this.#dbClient.query('ROLLBACK'); + return Promise.reject(); + } + } + + async moveOrderItem( {itemId, targetOrderId }){ + await this.#dbClient.query('BEGIN'); + try { + const item = await this.#dbClient.query( + 'SELECT id, order_id FROM order_items WHERE id = ?', [itemId] + ); + + // TODO + if (!item){ + return Promise.reject(); + } + + await this.#dbClient.query( + 'UPDATE order_items SET order_id = ? WHERE id = >', + [targetOrderId, itemId] + ); + + await this.#dbClient.query('COMMIT'); + } catch (err){ + await this.#dbClient.query('ROLLBACK'); + return Promise.reject(); + } + } } \ No newline at end of file diff --git a/server/server.js b/server/server.js index 61e53c2..d5d2d26 100644 --- a/server/server.js +++ b/server/server.js @@ -72,7 +72,7 @@ app.post('/api/current-date/advance', async (req, res) => { try { const raw_ids = await adapter.getOrdersByDate(currentDate); const ids = raw_ids.map(item => item.id); - await adapter.deleteOrdersByIds(ids); + await adapter.clearOrders(ids); let nextDate = AddDays(currentDate, 1); await setCurrentDate(nextDate); @@ -170,6 +170,115 @@ app.post('/api/orders', async (req, res) => { } }); +app.delete('/api/orders/:id', async (req, res) => { + try { + await adapter.deleteOrderById(req.params.id); + res.statusCode = 200; + res.message = "OK"; + res.json({message: "success"}); + } catch (err){ + res.statusCode = 500; + res.message = "WHOOPS"; + res.json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + error: `${err}` + }); + } +}) + +app.post('/api/orders/:orderId/items', async (req, res) => { + let orderId = req.params.orderId; + let { productId, quantity } = req.body; + + try { + await adapter.addOrderItem({ + orderId, + productId, + quantity + }); + + res.status(201).json({ + orderId, + productId, + quantity + }); + + } catch (err) { + // TODO + res.status(500).json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + }); + } +}); + +app.put('/api/orders/:orderId/items/:itemId', async (req, res) => { + let itemId = req.params.itemId; + let quantity = req.body.quantity; + + try { + await adapter.updateOrderItem({ + itemId, + quantity + }); + + res.status(201).json({ + itemId, + quantity + }); + + } catch (err) { + // TODO + res.status(500).json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + }); + } +}); + +app.delete('/api/orders/:orderId/items/:itemId', async (req, res) => { + try { + await adapter.deleteOrderItem(req.params.itemId); + res.statusCode = 204; + res.message = "OK"; + res.json({message: "success"}); + } catch (err){ + res.statusCode = 500; + res.message = "WHOOPS"; + res.json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + error: `${err}` + }); + } +}) + +app.post('/api/order-items/:itemId/move', async (req, res) => { + let itemId = req.params.itemId; + let targetOrderId = req.body.targetOrderId; + + try { + await adapter.moveOrderItem({ + itemId, + targetOrderId, + }); + + res.status(201).json({ + itemId, + targetOrderId, + }); + + } catch (err) { + // TODO + res.status(500).json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + }); + } +}); + + app.use((req, res) => { res.status(404).json({ error: 'Invalid route' }); });