From 4061f05e7c92dcb50c9afd34916df4f3e727e973 Mon Sep 17 00:00:00 2001 From: ViktoriiaRepo Date: Mon, 20 May 2024 17:15:20 +0300 Subject: [PATCH 1/3] Add task --- src/controllers/expenses.controllers.js | 75 ++++++++++++++++++++++ src/controllers/user.controllers.js | 84 +++++++++++++++++++++++++ src/createServer.js | 21 ++++++- src/db.js | 2 +- src/models/Expense.model.js | 35 ++++++++++- src/models/User.model.js | 14 ++++- src/routes/expenses.routes.js | 19 ++++++ src/routes/user.routes.js | 19 ++++++ src/services/expenses.services.js | 47 ++++++++++++++ src/services/user.services.js | 42 +++++++++++++ src/setup.js | 6 ++ src/utils/getFilteredxpense.js | 20 ++++++ 12 files changed, 378 insertions(+), 6 deletions(-) create mode 100644 src/controllers/expenses.controllers.js create mode 100644 src/controllers/user.controllers.js create mode 100644 src/routes/expenses.routes.js create mode 100644 src/routes/user.routes.js create mode 100644 src/services/expenses.services.js create mode 100644 src/services/user.services.js create mode 100644 src/setup.js create mode 100644 src/utils/getFilteredxpense.js diff --git a/src/controllers/expenses.controllers.js b/src/controllers/expenses.controllers.js new file mode 100644 index 00000000..3b604898 --- /dev/null +++ b/src/controllers/expenses.controllers.js @@ -0,0 +1,75 @@ +const expensesService = require('../services/expenses.services'); + +const getAll = async (req, res) => { + const query = req.query; + const expenses = await expensesService.get(query); + + res.send(expenses); +}; + +const getOne = async (req, res) => { + const { id } = req.params; + const expense = await expensesService.getById(id); + + if (!expense) { + res.sendStatus(404); + + return; + } + + res.statusCode = 200; + res.send(expense); +}; + +const add = async (req, res) => { + const body = req.body; + const userId = parseInt(body.userId); + + if (!userId) { + res.sendStatus(400); + + return; + } + + const expense = await expensesService.add(body); + + res.statusCode = 201; + res.send(expense); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + try { + await expensesService.remove(id); + + res.sendStatus(204); + } catch (error) { + res.sendStatus(404); + } +}; + +const update = async (req, res) => { + const { id } = req.params; + const body = req.body; + const expense = await expensesService.getById(id); + + if (!expense) { + res.sendStatus(404); + + return; + } + + const updatedExpense = await expensesService.update(expense.id, body); + + res.statusCode = 200; + res.send(updatedExpense); +}; + +module.exports = { + getAll, + add, + getOne, + remove, + update, +}; diff --git a/src/controllers/user.controllers.js b/src/controllers/user.controllers.js new file mode 100644 index 00000000..279d5d80 --- /dev/null +++ b/src/controllers/user.controllers.js @@ -0,0 +1,84 @@ +const userService = require('../services/user.services'); + +const getAll = async (req, res) => { + const users = await userService.getAll(); + + res.send(users); +}; + +const getOne = async (req, res) => { + const { id } = req.params; + + const user = await userService.getUserById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + res.status(200).send(user); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name) { + res.sendStatus(400); + + return; + } + + const user = await userService.create(name); + + res.statusCode = 201; + + res.status(201).send(user); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + const user = await userService.getUserById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + userService.remove(id); + + res.sendStatus(204); +}; + +const update = async (req, res) => { + const { id } = req.params; + const { name } = req.body; + + const user = userService.getUserById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + if (typeof name !== 'string') { + res.sendStatus(422); + + return; + } + + const updatedUser = await userService.update({ id, name }); + + res.send(updatedUser); +}; + +module.exports = { + getAll, + getOne, + create, + remove, + update, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..27f26131 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,23 @@ 'use strict'; -const createServer = () => { - // your code goes here -}; +const express = require('express'); +const cors = require('cors'); + +const { userRouter } = require('./routes/user.routes'); +const { expensesRouter } = require('./routes/expenses.routes'); + +function createServer() { + const app = express(); + + app.use(cors()); + + app.use(express.json()); + + app.use('/users', userRouter); + app.use('/expenses', expensesRouter); + + return app; +} module.exports = { createServer, diff --git a/src/db.js b/src/db.js index 1ba3046c..8226c6fc 100644 --- a/src/db.js +++ b/src/db.js @@ -26,7 +26,7 @@ const sequelize = new Sequelize({ host: POSTGRES_HOST || 'localhost', dialect: 'postgres', port: POSTGRES_PORT || 5432, - password: POSTGRES_PASSWORD || '123', + password: POSTGRES_PASSWORD, }); module.exports = { diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..d7d3f664 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,42 @@ 'use strict'; const { sequelize } = require('../db.js'); +const { DataTypes } = require('sequelize'); const Expense = sequelize.define( - // your code goes here + 'Expense', + { + userId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + spentAt: { + type: DataTypes.STRING, + defaultValue: DataTypes.NOW, + allowNull: false, + }, + title: { + type: DataTypes.STRING, + allowNull: false, + }, + amount: { + type: DataTypes.INTEGER, + allowNull: false, + }, + category: { + type: DataTypes.STRING, + allowNull: true, + }, + note: { + type: DataTypes.STRING, + allowNull: true, + }, + }, + { + tableName: 'expenses', + createdAt: false, + updatedAt: false, + }, ); module.exports = { diff --git a/src/models/User.model.js b/src/models/User.model.js index 61861c9e..55b6d7db 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,21 @@ 'use strict'; const { sequelize } = require('../db.js'); +const { DataTypes } = require('sequelize'); const User = sequelize.define( - // your code goes here + 'User', + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + tableName: 'users', + createdAt: false, + updatedAt: false, + }, ); module.exports = { diff --git a/src/routes/expenses.routes.js b/src/routes/expenses.routes.js new file mode 100644 index 00000000..7c472bfa --- /dev/null +++ b/src/routes/expenses.routes.js @@ -0,0 +1,19 @@ +const express = require('express'); + +const expenseConroller = require('../controllers/expenses.controllers'); + +const expensesRouter = express.Router(); + +expensesRouter.get('/', expenseConroller.getAll); + +expensesRouter.get('/:id', expenseConroller.getOne); + +expensesRouter.post('/', expenseConroller.add); + +expensesRouter.delete('/:id', expenseConroller.remove); + +expensesRouter.patch('/:id', expenseConroller.update); + +module.exports = { + expensesRouter, +}; diff --git a/src/routes/user.routes.js b/src/routes/user.routes.js new file mode 100644 index 00000000..ed48c2eb --- /dev/null +++ b/src/routes/user.routes.js @@ -0,0 +1,19 @@ +const express = require('express'); + +const userController = require('../controllers/user.controllers'); + +const userRouter = express.Router(); + +userRouter.get('/', userController.getAll); + +userRouter.get('/:id', userController.getOne); + +userRouter.post('/', userController.create); + +userRouter.delete('/:id', userController.remove); + +userRouter.patch('/:id', userController.update); + +module.exports = { + userRouter, +}; diff --git a/src/services/expenses.services.js b/src/services/expenses.services.js new file mode 100644 index 00000000..36b24370 --- /dev/null +++ b/src/services/expenses.services.js @@ -0,0 +1,47 @@ +const { Expense } = require('../models/Expense.model'); +const { getFilteredExpenses } = require('../utils/getFilteredxpense'); + +const get = async (query) => { + const filteredExpenses = getFilteredExpenses(query); + + return Expense.findAll({ + where: filteredExpenses, + }); +}; + +const getById = (id) => { + return Expense.findByPk(id); +}; + +const add = async (data) => { + return Expense.create(data); +}; + +const remove = async (id) => { + Expense.destroy({ + where: { + id, + }, + }); +}; + +const update = async (id, data) => { + await Expense.update( + { ...data }, + { + where: { + id, + }, + }, + ); + + return Expense.findByPk(id); +}; + +module.exports = { + get, + add, + getById, + remove, + update, +}; diff --git a/src/services/user.services.js b/src/services/user.services.js new file mode 100644 index 00000000..29dee9ab --- /dev/null +++ b/src/services/user.services.js @@ -0,0 +1,42 @@ +const { User } = require('../models/User.model'); + +const getAll = () => { + return User.findAll(); +}; + +const getUserById = (id) => { + return User.findByPk(id); +}; + +const create = (name) => { + return User.create({ name }); +}; + +const remove = async (id) => { + User.destroy({ + where: { + id, + }, + }); +}; + +const update = async ({ id, name }) => { + await User.update( + { name }, + { + where: { + id, + }, + }, + ); + + return getUserById(id); +}; + +module.exports = { + getAll, + getUserById, + create, + remove, + update, +}; diff --git a/src/setup.js b/src/setup.js new file mode 100644 index 00000000..7e6892a2 --- /dev/null +++ b/src/setup.js @@ -0,0 +1,6 @@ +const { User } = require('./models/User.model'); +const { Expense } = require('./models/Expense.model'); + +User.sync({ force: true }); + +Expense.sync({ force: true }); diff --git a/src/utils/getFilteredxpense.js b/src/utils/getFilteredxpense.js new file mode 100644 index 00000000..77646cad --- /dev/null +++ b/src/utils/getFilteredxpense.js @@ -0,0 +1,20 @@ +const { Sequelize } = require('sequelize'); + +const getFilteredExpenses = ({ userId, categories, from, to }) => { + const filterParams = { + ...(userId && { userId }), + ...(categories && { category: categories }), + ...((from || to) && { + spentAt: { + ...(from && { [Sequelize.Op.gte]: from }), + ...(to && { [Sequelize.Op.lte]: to }), + }, + }), + }; + + return filterParams; +}; + +module.exports = { + getFilteredExpenses, +}; From ef85966abbd30843eb59467a3ef33573b94b8e99 Mon Sep 17 00:00:00 2001 From: ViktoriiaRepo Date: Mon, 3 Jun 2024 22:10:10 +0300 Subject: [PATCH 2/3] Add statusCode --- src/controllers/expenses.controllers.js | 41 +++++++++++++++++-------- src/controllers/user.controllers.js | 2 -- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/controllers/expenses.controllers.js b/src/controllers/expenses.controllers.js index 3b604898..bbd31679 100644 --- a/src/controllers/expenses.controllers.js +++ b/src/controllers/expenses.controllers.js @@ -1,5 +1,14 @@ const expensesService = require('../services/expenses.services'); +const statusCode = { + OK: 200, + CREATED: 201, + NO_CONTENT: 204, + BAD_REQUEST: 400, + NOT_FOUND: 404, + INTERNAL_SERVER_ERROR: 500, +}; + const getAll = async (req, res) => { const query = req.query; const expenses = await expensesService.get(query); @@ -12,12 +21,12 @@ const getOne = async (req, res) => { const expense = await expensesService.getById(id); if (!expense) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); return; } - res.statusCode = 200; + res.statusCode = statusCode; res.send(expense); }; @@ -26,15 +35,19 @@ const add = async (req, res) => { const userId = parseInt(body.userId); if (!userId) { - res.sendStatus(400); + res.sendStatus(statusCode.BAD_REQUEST); return; } - const expense = await expensesService.add(body); + try { + const expense = await expensesService.add(body); - res.statusCode = 201; - res.send(expense); + res.statusCode = statusCode.CREATED; + res.send(expense); + } catch (error) { + res.status(statusCode.INTERNAL_SERVER_ERROR).send(error.message); + } }; const remove = async (req, res) => { @@ -43,9 +56,9 @@ const remove = async (req, res) => { try { await expensesService.remove(id); - res.sendStatus(204); + res.sendStatus(statusCode.NO_CONTENT); } catch (error) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); } }; @@ -55,15 +68,19 @@ const update = async (req, res) => { const expense = await expensesService.getById(id); if (!expense) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); return; } - const updatedExpense = await expensesService.update(expense.id, body); + try { + const updatedExpense = await expensesService.update(expense.id, body); - res.statusCode = 200; - res.send(updatedExpense); + res.statusCode = statusCode.OK; + res.send(updatedExpense); + } catch (error) { + res.status(statusCode.INTERNAL_SERVER_ERROR).send(error.message); + } }; module.exports = { diff --git a/src/controllers/user.controllers.js b/src/controllers/user.controllers.js index 279d5d80..71e24945 100644 --- a/src/controllers/user.controllers.js +++ b/src/controllers/user.controllers.js @@ -31,8 +31,6 @@ const create = async (req, res) => { const user = await userService.create(name); - res.statusCode = 201; - res.status(201).send(user); }; From aea224df28c95c1ccc672ba5d17ef3021b9af8c5 Mon Sep 17 00:00:00 2001 From: ViktoriiaRepo Date: Mon, 3 Jun 2024 23:26:03 +0300 Subject: [PATCH 3/3] Change after checking --- src/controllers/expenses.controllers.js | 32 +++++++------------------ src/controllers/user.controllers.js | 17 ++++++------- src/helpers/statusCode.js | 10 ++++++++ 3 files changed, 27 insertions(+), 32 deletions(-) create mode 100644 src/helpers/statusCode.js diff --git a/src/controllers/expenses.controllers.js b/src/controllers/expenses.controllers.js index bbd31679..bb9b8332 100644 --- a/src/controllers/expenses.controllers.js +++ b/src/controllers/expenses.controllers.js @@ -1,13 +1,5 @@ const expensesService = require('../services/expenses.services'); - -const statusCode = { - OK: 200, - CREATED: 201, - NO_CONTENT: 204, - BAD_REQUEST: 400, - NOT_FOUND: 404, - INTERNAL_SERVER_ERROR: 500, -}; +const { statusCode } = require('../helpers/statusCode'); const getAll = async (req, res) => { const query = req.query; @@ -26,7 +18,7 @@ const getOne = async (req, res) => { return; } - res.statusCode = statusCode; + res.statusCode = 200; res.send(expense); }; @@ -40,14 +32,10 @@ const add = async (req, res) => { return; } - try { - const expense = await expensesService.add(body); + const expense = await expensesService.add(body); - res.statusCode = statusCode.CREATED; - res.send(expense); - } catch (error) { - res.status(statusCode.INTERNAL_SERVER_ERROR).send(error.message); - } + res.statusCode = statusCode.CREATED; + res.send(expense); }; const remove = async (req, res) => { @@ -73,14 +61,10 @@ const update = async (req, res) => { return; } - try { - const updatedExpense = await expensesService.update(expense.id, body); + const updatedExpense = await expensesService.update(expense.id, body); - res.statusCode = statusCode.OK; - res.send(updatedExpense); - } catch (error) { - res.status(statusCode.INTERNAL_SERVER_ERROR).send(error.message); - } + res.statusCode = statusCode.OK; + res.send(updatedExpense); }; module.exports = { diff --git a/src/controllers/user.controllers.js b/src/controllers/user.controllers.js index 71e24945..00273c03 100644 --- a/src/controllers/user.controllers.js +++ b/src/controllers/user.controllers.js @@ -1,4 +1,5 @@ const userService = require('../services/user.services'); +const { statusCode } = require('../helpers/statusCode'); const getAll = async (req, res) => { const users = await userService.getAll(); @@ -12,26 +13,26 @@ const getOne = async (req, res) => { const user = await userService.getUserById(id); if (!user) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); return; } - res.status(200).send(user); + res.status(statusCode.OK).send(user); }; const create = async (req, res) => { const { name } = req.body; if (!name) { - res.sendStatus(400); + res.sendStatus(statusCode.BAD_REQUEST); return; } const user = await userService.create(name); - res.status(201).send(user); + res.status(statusCode.CREATED).send(user); }; const remove = async (req, res) => { @@ -40,14 +41,14 @@ const remove = async (req, res) => { const user = await userService.getUserById(id); if (!user) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); return; } userService.remove(id); - res.sendStatus(204); + res.sendStatus(statusCode.NO_CONTENT); }; const update = async (req, res) => { @@ -57,13 +58,13 @@ const update = async (req, res) => { const user = userService.getUserById(id); if (!user) { - res.sendStatus(404); + res.sendStatus(statusCode.NOT_FOUND); return; } if (typeof name !== 'string') { - res.sendStatus(422); + res.sendStatus(statusCode.UNPROCESSABLE_ENTITY); return; } diff --git a/src/helpers/statusCode.js b/src/helpers/statusCode.js new file mode 100644 index 00000000..6ba4d51a --- /dev/null +++ b/src/helpers/statusCode.js @@ -0,0 +1,10 @@ +const statusCode = { + OK: 200, + CREATED: 201, + NO_CONTENT: 204, + BAD_REQUEST: 400, + NOT_FOUND: 404, + UNPROCESSABLE_ENTITY: 422, +}; + +module.exports = { statusCode };