From bfde13afd0578428adce20decc20f3de0fd37ccb Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Tue, 30 Dec 2025 15:08:35 +0300 Subject: [PATCH] /api/products and /api/orders --- package.json | 35 +++++---- server.js | 42 ----------- server/db/database.js | 97 +++++++++++++++++++++++++ server/server.js | 162 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 276 insertions(+), 60 deletions(-) delete mode 100644 server.js create mode 100644 server/db/database.js create mode 100644 server/server.js diff --git a/package.json b/package.json index b96e1cf..bfb34cd 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,19 @@ { - "name": "deliver_man", - "version": "1.0.0", - "description": "", - "main": "server.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "node server.js" - }, - "keywords": [], - "author": "", - "license": "ISC", - "type": "commonjs", - "dependencies": { - "express": "^5.2.1" - }, - "devDependencies": { - "nodemon": "^3.1.11" - } + "name": "deliver-man-server", + "version": "1.0.0", + "description": "", + "main": "server.js", + "type": "module", + "scripts": { + "start": "node server/server.js", + "dev": "nodemon server/server.js" + }, + "dependencies": { + "dotenv": "^17.2.3", + "express": "^4.22.1", + "mariadb": "^3.4.5" + }, + "devDependencies": { + "nodemon": "^3.0.1" + } } diff --git a/server.js b/server.js deleted file mode 100644 index d9c5261..0000000 --- a/server.js +++ /dev/null @@ -1,42 +0,0 @@ -const express = require('express'); -const app = express(); -const PORT = process.env.PORT || 3000; - -app.use(express.json()); - -app.get('/', (req, res) => { - res.json({ - message: 'Hello, World!', - status: 'OK' - }); -}); - -app.get('/health', (req, res) => { - res.status(200).json({ - status: 'healthy', - timestamp: new Date().toISOString() - }); -}); - -app.post('/api/data', (req, res) => { - const data = req.body; - res.json({ - message: 'Data received', - data: data, - timestamp: new Date().toISOString() - }); -}); - -app.use((req, res) => { - res.status(404).json({ error: 'Invalid route' }); -}); - -app.use((err, req, res, next) => { - console.error(err.stack); - res.status(500).json({ error: 'Something went wrong!' }); -}); - -app.listen(PORT, () => { - console.log(`✅ Server running on port ${PORT}`); - console.log(`📡 Local: http://localhost:${PORT}`); -}); \ No newline at end of file diff --git a/server/db/database.js b/server/db/database.js new file mode 100644 index 0000000..cc4cf83 --- /dev/null +++ b/server/db/database.js @@ -0,0 +1,97 @@ +import mdb from "mariadb" + +export default class DBAdapter { + #dbhost = 'localhost'; + #dbPort = 3306; + #dbName = 'N'; + #dbUserLogin = 'u'; + #dbUserPassword = 'p'; + #dbClient = null; + + constructor({ + dbHost, + dbPort, + dbName, + dbUserLogin, + dbUserPassword + }) { + this.#dbhost = dbHost; + this.#dbPort = dbPort; + this.#dbName = dbName; + this.#dbUserLogin = dbUserLogin; + this.#dbUserPassword = dbUserPassword; + this.#dbClient = new mdb.createPool({ + host: this.#dbhost, + port: this.#dbPort, + database: this.#dbName, + user: this.#dbUserLogin, + password: this.#dbUserPassword + }); + } + + async connect() { + try { + // Проверяем подключение, выполняя простой запрос + const conn = await this.#dbClient.getConnection(); + console.log("✅ Database connection test successful"); + conn.release(); + } catch (err) { + console.error("❌ Database connection failed:", err.message); + // Пробрасываем ошибку дальше + return Promise.reject(); + } + } + + async disconnect() { + await this.#dbClient.end(); + console.log("DISCONNECT"); + } + + async getProducts() { + try { + const products = await this.#dbClient.query('SELECT * FROM products ORDER BY name'); + console.log("All products:", products); + return products; + } catch(err){ + console.log(`WHOOPS`); + return Promise.reject(); + } + } + + async getOrders() { + try { + const raw_orders = await this.#dbClient.query('SELECT * FROM orders ORDER BY order_date ASC'); + console.log("All orders:", raw_orders); + + const items = await this.#dbClient.query( + `SELECT order_items.*, products.name AS product_name FROM order_items + JOIN products ON order_items.product_id = products.id` + ); + console.log("All order items:", items); + + const groupedItems = {}; + if (items && items.length > 0) { + items.forEach(item => { + const orderId = item.order_id; + if (!groupedItems[orderId]) { + groupedItems[orderId] = []; + } + groupedItems[orderId].push(item); + }); + } + + const ordersWithItems = raw_orders.map(order => { + return { + ...order, + items: groupedItems[order.id] || [] + }; + }); + + console.log("Orders with items:", ordersWithItems); + return ordersWithItems; + } catch(err) { + console.log(`WHOOPS: ${err.message}`); + return Promise.reject(err); + } + } +} \ No newline at end of file diff --git a/server/server.js b/server/server.js new file mode 100644 index 0000000..cc3eb57 --- /dev/null +++ b/server/server.js @@ -0,0 +1,162 @@ +import express from "express"; +import randomUUID from "crypto"; +import dotenv from "dotenv" +import DBAdapter from "./db/database.js"; +import { error, timeStamp } from "console"; + +dotenv.config({ + path: './server/.env' +}); + +const { + HOST, + PORT, + DATABASE, + USER, + PASSWORD +} = process.env; + +const app = express(); +app.use(express.json()); + +const adapter = new DBAdapter({ + dbHost: HOST, + dbPort: PORT, + dbName: DATABASE, + dbUserLogin: USER, + dbUserPassword: PASSWORD +}); + +let currentDate = (new Date()).toISOString().slice(0, 10); + +async function getCurrentDate() { + return currentDate; +} +function AddDays(dateString, days) { + let date = new Date(dateString); + date.setDate(date.getDate() + days); + return formatDate(date); +} + +function Random_Increase() { + return Math.floor(Math.random() * 5) + 1; +} + +app.get('/api/current-date', async (req, res) => { + let currentDate = await getCurrentDate(); + res.json({ currentDate }); +}); + +app.get('/api/products', async(req, res) => { + try { + const db_products = await adapter.getProducts(); + + const products = db_products.map( + ( {id, name, quantity} ) => ({ + ID: id, + pr_name: name, + count: quantity + }) + ); + res.statusCode = 200; + res.message = "OK"; + res.json(products); + } catch (err){ + res.statusCode = 500; + res.message = "WHOOPS"; + res.json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + error : `${err}` + }) + } +}); + +app.post('/api/current-date/advance', async (req, res) => { + let currentDate = await getCurrentDate(); + // TODO: select orders with current date and delete them from database + + // TODO: get all products and increase with Random_Increase() + + let nextDate = AddDays(currentDate, 1); + currentDate = nextDate; + res.json({ currentDate: nextDate }); +}); + +app.get('/api/orders', async(req, res) => { + try { + const db_orders = await adapter.getOrders(); + + const orders = db_orders.map( + ( {id, customer_name, order_date, status, total_amount, items} ) => ({ + ID: id, + customer: customer_name, + date: order_date, + status: status, + total: total_amount, + items: items ? items.map(item => ({ + product_id: item.product_id, + product_name: item.product_name || item.name, + quantity: item.quantity, + price: item.price + })) : [] + }) + ); + + res.statusCode = 200; + res.message = "OK"; + res.json(orders); + + } catch (err) { + res.statusCode = 500; + res.message = "WHOOPS"; + res.json({ + timeStamp: new Date().toISOString(), + statusCode: 500, + error: `${err}` + }); + } +}); + +app.post('/api/orders', async (req, res) => { + let { customerName, orderDate } = req.body; + if (!customerName || !orderDate) { + return res.status(400).json({ message: 'Full name and date, please!' }); + } + let currentDate = await getCurrentDate(); + if (orderDate < currentDate) { + return res.status(400).json({ message: 'Date of order can\'t be more, than current!' }); + } + let id = randomUUID(); + // TODO: Insert id into orders + + res.status(201).json({ id, customer_name: customerName, date: orderDate }); +}); + +app.use((req, res) => { + res.status(404).json({ error: 'Invalid route' }); +}); + +app.use((err, req, res, next) => { + console.error(err.stack); + res.status(500).json({ error: 'Something went wrong!' }); +}); + +app.listen(3000, async() => { + try { + await adapter.connect(); + console.log(`✅ Server running on port 3000`); + console.log(`📡 Local: http://localhost:3000`); + } catch(err){ + console.log("Shutting down application..."); + process.exit(100); + } +}); + +process.on('SIGTERM', () => { + console.log("CLOSE APP"); + app.close( async() => { + await adapter.disconnect(); + console.log("DB DISCONNECTED"); + }); +}); \ No newline at end of file