From d11e1b3e3d1a5ee1b76d947ea3549c33695c349a Mon Sep 17 00:00:00 2001 From: Podvoiskyi Oleksandr Date: Fri, 2 Aug 2024 22:04:08 +0300 Subject: [PATCH] add task solution --- src/controllers/expenses.controller.js | 99 ++++++++++++++++++++++++++ src/controllers/users.controller.js | 83 +++++++++++++++++++++ src/createServer.js | 19 ++++- src/models/Expense.model.js | 35 ++++++++- src/models/User.model.js | 17 ++++- src/routers/expenses.router.js | 12 ++++ src/routers/users.router.js | 12 ++++ src/services/expenses.service.js | 90 +++++++++++++++++++++++ src/services/users.service.js | 41 +++++++++++ 9 files changed, 403 insertions(+), 5 deletions(-) create mode 100644 src/controllers/expenses.controller.js create mode 100644 src/controllers/users.controller.js create mode 100644 src/routers/expenses.router.js create mode 100644 src/routers/users.router.js create mode 100644 src/services/expenses.service.js create mode 100644 src/services/users.service.js diff --git a/src/controllers/expenses.controller.js b/src/controllers/expenses.controller.js new file mode 100644 index 00000000..6cd03864 --- /dev/null +++ b/src/controllers/expenses.controller.js @@ -0,0 +1,99 @@ +const expensesServise = require('../services/expenses.service'); +const { getById: getUserById } = require('../services/users.service'); + +const getAll = async (req, res) => { + const expenses = await expensesServise.getAll(req.query); + + res.json(expenses.map(expensesServise.normalize)); +}; + +const create = async (req, res) => { + const { userId, spentAt, title, amount, category, note } = req.body; + + const user = await getUserById(userId); + + if (!user || !userId || !spentAt || !title || !amount || isNaN(+amount)) { + return res.sendStatus(400); + } + + const newExpense = await expensesServise.create({ + userId, + spentAt, + title, + amount: +amount, + category, + note, + }); + + res.status(201).json(expensesServise.normalize(newExpense)); +}; + +const getById = async (req, res) => { + const { id } = req.params; + const numId = +id; + + if (!id || isNaN(numId)) { + return res.sendStatus(400); + } + + const expense = await expensesServise.getById(numId); + + if (!expense) { + return res.sendStatus(404); + } + + res.json(expensesServise.normalize(expense)); +}; + +const deleteById = async (req, res) => { + const { id } = req.params; + const numId = +id; + + if (!id || isNaN(numId)) { + return res.sendStatus(400); + } + + const expense = await expensesServise.getById(numId); + + if (!expense) { + return res.sendStatus(404); + } + + await expensesServise.deleteById(numId); + + res.status(204).json(expensesServise.normalize(expense)); +}; + +const updateById = async (req, res) => { + const { id } = req.params; + const { spentAt, title, amount, category, note } = req.body; + const numId = +id; + + const expense = await expensesServise.getById(numId); + + if (!expense) { + return res.sendStatus(404); + } + + if (!spentAt && !title && !amount && !category && !note) { + return res.sendStatus(400); + } + + const updatedExpense = await expensesServise.updateById(id, { + spentAt: spentAt || expense.spentAt, + title: title || expense.title, + amount: amount || expense.amount, + category: category || expense.category, + note: note || expense.note, + }); + + res.json(expensesServise.normalize(updatedExpense)); +}; + +module.exports = { + getAll, + create, + getById, + deleteById, + updateById, +}; diff --git a/src/controllers/users.controller.js b/src/controllers/users.controller.js new file mode 100644 index 00000000..19543024 --- /dev/null +++ b/src/controllers/users.controller.js @@ -0,0 +1,83 @@ +const usersService = require('../services/users.service'); + +const getAll = async (req, res) => { + const users = await usersService.getAll(); + + res.json(users.map(usersService.normalize)); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name) { + return res.sendStatus(400); + } + + const newUser = await usersService.create(name); + + res.status(201).json(usersService.normalize(newUser)); +}; + +const getById = async (req, res) => { + const { id } = req.params; + const numId = +id; + + if (!id || isNaN(numId)) { + return res.sendStatus(400); + } + + const user = await usersService.getById(numId); + + if (!user) { + return res.sendStatus(404); + } + + res.json(usersService.normalize(user)); +}; + +const deleteById = async (req, res) => { + const { id } = req.params; + const numId = +id; + + if (!id || isNaN(numId)) { + return res.sendStatus(400); + } + + const user = await usersService.getById(numId); + + if (!user) { + return res.sendStatus(404); + } + + await usersService.deleteById(numId); + + res.status(204).json(usersService.normalize(user)); +}; + +const updateById = async (req, res) => { + const { id } = req.params; + const { name } = req.body; + const numId = +id; + + if (!id || !name || isNaN(numId)) { + return res.sendStatus(400); + } + + const user = await usersService.getById(numId); + + if (!user) { + return res.sendStatus(404); + } + + const updatedUser = await usersService.updateById(numId, { name }); + + res.json(usersService.normalize(updatedUser)); +}; + +module.exports = { + getAll, + create, + getById, + deleteById, + updateById, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..2ac51884 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,21 @@ 'use strict'; -const createServer = () => { - // your code goes here -}; +const express = require('express'); +const cors = require('cors'); +const { usersRouter } = require('./routers/users.router.js'); +const { expensesRouter } = require('./routers/expenses.router.js'); + +function createServer() { + const app = express(); + + app.use(express.json()); + app.use(cors()); + + app.use('/users', usersRouter); + app.use('/expenses', expensesRouter); + + return app; +} module.exports = { createServer, diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..7b5069c8 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,42 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const Expense = sequelize.define( - // your code goes here + 'Expense', + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + userId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + spentAt: { + type: DataTypes.STRING, + allowNull: false, + }, + title: { + type: DataTypes.STRING, + allowNull: false, + }, + amount: { + type: DataTypes.INTEGER, + allowNull: false, + }, + category: { + type: DataTypes.STRING, + }, + note: { + type: DataTypes.STRING, + }, + }, + { + tableName: 'expenses', + }, ); module.exports = { diff --git a/src/models/User.model.js b/src/models/User.model.js index 61861c9e..b5773b4d 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,24 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const User = sequelize.define( - // your code goes here + 'User', + { + id: { + type: DataTypes.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + tableName: 'users', + }, ); module.exports = { diff --git a/src/routers/expenses.router.js b/src/routers/expenses.router.js new file mode 100644 index 00000000..7b86c714 --- /dev/null +++ b/src/routers/expenses.router.js @@ -0,0 +1,12 @@ +const { Router } = require('express'); +const expensesController = require('../controllers/expenses.controller'); + +const expensesRouter = Router(); + +expensesRouter.get('/', expensesController.getAll); +expensesRouter.post('/', expensesController.create); +expensesRouter.get('/:id', expensesController.getById); +expensesRouter.delete('/:id', expensesController.deleteById); +expensesRouter.patch('/:id', expensesController.updateById); + +module.exports = { expensesRouter }; diff --git a/src/routers/users.router.js b/src/routers/users.router.js new file mode 100644 index 00000000..1dc6f1ed --- /dev/null +++ b/src/routers/users.router.js @@ -0,0 +1,12 @@ +const { Router } = require('express'); +const usersController = require('../controllers/users.controller'); + +const usersRouter = Router(); + +usersRouter.get('/', usersController.getAll); +usersRouter.post('/', usersController.create); +usersRouter.get('/:id', usersController.getById); +usersRouter.delete('/:id', usersController.deleteById); +usersRouter.patch('/:id', usersController.updateById); + +module.exports = { usersRouter }; diff --git a/src/services/expenses.service.js b/src/services/expenses.service.js new file mode 100644 index 00000000..47ac66aa --- /dev/null +++ b/src/services/expenses.service.js @@ -0,0 +1,90 @@ +const { Expense } = require('../models/Expense.model'); + +const normalize = ({ id, userId, spentAt, title, amount, category, note }) => { + return { + id, + userId, + spentAt, + title, + amount, + category, + note, + }; +}; + +const getAll = async ({ userId, from, to, categories }) => { + const result = await Expense.findAll(); + + const filteredExpenses = result.filter((expense) => { + if (userId && expense.userId !== +userId) { + return false; + } + + if (from && new Date(expense.spentAt) < new Date(from)) { + return false; + } + + if (to && new Date(expense.spentAt) > new Date(to)) { + return false; + } + + if (categories && !categories.includes(expense.category)) { + return false; + } + + return true; + }); + + return filteredExpenses; +}; + +const getById = async (id) => { + const numId = +id; + + if (isNaN(numId)) { + return; + } + + return Expense.findByPk(numId); +}; + +const create = async ({ userId, spentAt, title, amount, category, note }) => { + return Expense.create({ + userId, + spentAt, + title, + amount, + category, + note, + }); +}; + +const deleteById = async (id) => { + await Expense.destroy({ + where: { id }, + }); +}; + +const updateById = async (id, { spentAt, title, amount, category, note }) => { + await Expense.update( + { + spentAt, + title, + amount, + category, + note, + }, + { where: { id } }, + ); + + return Expense.findByPk(id); +}; + +module.exports = { + getAll, + getById, + create, + deleteById, + updateById, + normalize, +}; diff --git a/src/services/users.service.js b/src/services/users.service.js new file mode 100644 index 00000000..b6239f1d --- /dev/null +++ b/src/services/users.service.js @@ -0,0 +1,41 @@ +const { User } = require('../models/User.model'); + +const normalize = ({ id, name }) => { + return { + id, + name, + }; +}; + +const getAll = async () => { + const result = await User.findAll(); + + return result; +}; + +const getById = async (id) => { + return User.findByPk(id); +}; + +const create = async (name) => { + return User.create({ name }); +}; + +const deleteById = async (id) => { + await User.destroy({ where: { id } }); +}; + +const updateById = async (id, { name }) => { + await User.update({ name }, { where: { id } }); + + return User.findByPk(id); +}; + +module.exports = { + getAll, + getById, + create, + deleteById, + updateById, + normalize, +};