From cc676c3ea2c6fb3734526e4a9a68983e9cce3d66 Mon Sep 17 00:00:00 2001 From: Alla Serhiienko Date: Thu, 1 Aug 2024 14:51:51 +0200 Subject: [PATCH] Solution --- src/controllers/expense.controller.js | 113 ++++++++++++++++++++++++++ src/controllers/user.controller.js | 83 +++++++++++++++++++ src/createServer.js | 17 +++- src/db.js | 8 +- src/models/Expense.model.js | 36 +++++++- src/models/User.model.js | 14 +++- src/routes/expense.router.js | 18 ++++ src/routes/user.router.js | 18 ++++ src/services/expense.service.js | 76 +++++++++++++++++ src/services/user.service.js | 37 +++++++++ src/setup.js | 3 + 11 files changed, 411 insertions(+), 12 deletions(-) create mode 100644 src/controllers/expense.controller.js create mode 100644 src/controllers/user.controller.js create mode 100644 src/routes/expense.router.js create mode 100644 src/routes/user.router.js create mode 100644 src/services/expense.service.js create mode 100644 src/services/user.service.js create mode 100644 src/setup.js diff --git a/src/controllers/expense.controller.js b/src/controllers/expense.controller.js new file mode 100644 index 00000000..e6db501b --- /dev/null +++ b/src/controllers/expense.controller.js @@ -0,0 +1,113 @@ +const expenseService = require('./../services/expense.service'); +const userService = require('./../services/user.service'); + +const get = async (req, res) => { + if (Object.keys(req.query).length === 0) { + res.send(await expenseService.getAll()); + + return; + } + + const { userId, categories, from, to } = req.query; + + const expenses = await expenseService.getFiltered({ + userId, + categories: categories ? categories.split(',') : [], + from, + to, + }); + + res.send(expenses); +}; + +const create = async (req, res) => { + const { userId, spentAt, title, amount, category, note } = req.body; + + if ( + !userId || + !spentAt || + !title || + !amount || + !userService.getById(userId) + ) { + res.sendStatus(400); + + return; + } + + const expense = await expenseService.create({ + userId, + spentAt, + title, + amount, + category, + note, + }); + + res.status(201).send(expense); +}; + +const getOne = async (req, res) => { + const id = +req.params.id; + + if (!id) { + res.sendStatus(400); + + return; + } + + const expense = await expenseService.getById(id); + + if (!expense) { + res.sendStatus(404); + + return; + } + + res.send(expense); +}; + +const remove = async (req, res) => { + const id = +req.params.id; + + if (!(await expenseService.getById(id))) { + res.sendStatus(404); + + return; + } + + await expenseService.remove(id); + res.sendStatus(204); +}; + +const update = async (req, res) => { + const id = +req.params.id; + const { spentAt, title, amount, category, note } = req.body; + + if (!(await expenseService.getById(id))) { + res.sendStatus(404); + + return; + } + + await expenseService.update({ + id, + spentAt, + title, + amount, + category, + note, + }); + + const updatedExpense = await expenseService.getById(id); + + res.send(updatedExpense); +}; + +module.exports = { + get, + create, + getOne, + remove, + update, +}; diff --git a/src/controllers/user.controller.js b/src/controllers/user.controller.js new file mode 100644 index 00000000..3f589d1c --- /dev/null +++ b/src/controllers/user.controller.js @@ -0,0 +1,83 @@ +const userService = require('./../services/user.service'); + +const get = async (req, res) => { + res.send(await userService.getAll()); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name || typeof name !== 'string') { + res.sendStatus(400); + + return; + } + + const user = await userService.create(name); + + res.status(201).send(user); +}; + +const getOne = async (req, res) => { + const id = +req.params.id; + + if (!id) { + res.sendStatus(400); + + return; + } + + const user = await userService.getById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + res.send(user); +}; + +const remove = async (req, res) => { + const id = +req.params.id; + + if (!(await userService.getById(id))) { + res.sendStatus(404); + + return; + } + + await userService.remove(id); + res.sendStatus(204); +}; + +const update = async (req, res) => { + const id = +req.params.id; + const { name } = req.body; + + if (!(await userService.getById(id))) { + res.sendStatus(404); + + return; + } + + if (typeof name !== 'string' || !name) { + res.sendStatus(400); + + return; + } + + await userService.update({ id, name }); + + const updatedUser = await userService.getById(id); + + res.send(updatedUser); +}; + +module.exports = { + get, + create, + getOne, + remove, + update, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..e48170eb 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,19 @@ 'use strict'; -const createServer = () => { - // your code goes here -}; +const express = require('express'); +const { userRouter } = require('./routes/user.router'); +const { expenseRouter } = require('./routes/expense.router'); + +function createServer() { + const app = express(); + + app.use(express.json()); + + app.use('/users', userRouter); + app.use('/expenses', expenseRouter); + + return app; +} module.exports = { createServer, diff --git a/src/db.js b/src/db.js index 1ba3046c..8355a40a 100644 --- a/src/db.js +++ b/src/db.js @@ -3,7 +3,6 @@ const { Sequelize } = require('sequelize'); const utils = require('util'); -// Needed for testing purposes, do not remove require('dotenv').config(); global.TextEncoder = utils.TextEncoder; @@ -15,18 +14,13 @@ const { POSTGRES_DB, } = process.env; -/* - All credentials setted to default values (exsept password - it is exapmle) - replace if needed with your own -*/ - const sequelize = new Sequelize({ database: POSTGRES_DB || 'postgres', username: POSTGRES_USER || 'postgres', host: POSTGRES_HOST || 'localhost', dialect: 'postgres', port: POSTGRES_PORT || 5432, - password: POSTGRES_PASSWORD || '123', + password: POSTGRES_PASSWORD || '2223', }); module.exports = { diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..2a570d1f 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,43 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const Expense = sequelize.define( - // your code goes here + 'Expense', + { + title: { + type: DataTypes.STRING, + allowNull: false, + }, + userId: { + type: DataTypes.INTEGER, + allowNull: false, + field: 'user_id', + }, + spentAt: { + type: DataTypes.DATE, + allowNull: false, + field: 'spent_at', + }, + amount: { + type: DataTypes.INTEGER, + allowNull: false, + }, + category: { + type: DataTypes.STRING, + allowNull: true, + }, + note: { + type: DataTypes.STRING, + allowNull: true, + }, + }, + { + tableName: 'expenses', + updatedAt: false, + createdAt: false, + }, ); module.exports = { diff --git a/src/models/User.model.js b/src/models/User.model.js index 61861c9e..043e80dc 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,21 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const User = sequelize.define( - // your code goes here + 'User', + { + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + tableName: 'users', + updatedAt: false, + createdAt: false, + }, ); module.exports = { diff --git a/src/routes/expense.router.js b/src/routes/expense.router.js new file mode 100644 index 00000000..62ce6375 --- /dev/null +++ b/src/routes/expense.router.js @@ -0,0 +1,18 @@ +const express = require('express'); +const expenseController = require('./../controllers/expense.controller'); + +const router = express.Router(); + +router.get('/', expenseController.get); + +router.get('/:id', expenseController.getOne); + +router.post('/', expenseController.create); + +router.delete('/:id', expenseController.remove); + +router.patch('/:id', expenseController.update); + +module.exports = { + expenseRouter: router, +}; diff --git a/src/routes/user.router.js b/src/routes/user.router.js new file mode 100644 index 00000000..f435aa87 --- /dev/null +++ b/src/routes/user.router.js @@ -0,0 +1,18 @@ +const express = require('express'); +const userController = require('./../controllers/user.controller'); + +const router = express.Router(); + +router.get('/', userController.get); + +router.get('/:id', userController.getOne); + +router.post('/', userController.create); + +router.delete('/:id', userController.remove); + +router.patch('/:id', userController.update); + +module.exports = { + userRouter: router, +}; diff --git a/src/services/expense.service.js b/src/services/expense.service.js new file mode 100644 index 00000000..012d68be --- /dev/null +++ b/src/services/expense.service.js @@ -0,0 +1,76 @@ +const { Op } = require('sequelize'); +const { Expense } = require('../models/Expense.model'); + +const getAll = () => { + return Expense.findAll(); +}; + +const getFiltered = async ({ userId, categories, from, to }) => { + const where = {}; + + if (userId) { + where.userId = userId; + } + + if (categories.length > 0) { + where.category = { + [Op.in]: categories, + }; + } + + if (from) { + where.spentAt = { + [Op.gte]: from, + }; + } + + if (to) { + where.spentAt = { + [Op.lte]: to, + }; + } + + const result = await Expense.findAll({ + where, + }); + + return result; +}; + +const create = (expenseData) => { + return Expense.create(expenseData); +}; + +const getById = (id) => { + return Expense.findByPk(id); +}; + +const remove = async (id) => { + await Expense.destroy({ + where: { + id, + }, + }); +}; + +const update = ({ id, spentAt, title, amount, category, note }) => { + return Expense.update( + { + spentAt, + title, + amount, + category, + note, + }, + { where: { id } }, + ); +}; + +module.exports = { + getAll, + getFiltered, + create, + getById, + remove, + update, +}; diff --git a/src/services/user.service.js b/src/services/user.service.js new file mode 100644 index 00000000..6895c2b9 --- /dev/null +++ b/src/services/user.service.js @@ -0,0 +1,37 @@ +const { User } = require('../models/User.model'); + +const getAll = async () => { + const result = await User.findAll({ + order: [['name', 'ASC']], + }); + + return result; +}; + +const create = (name) => { + return User.create({ name }); +}; + +const getById = (id) => { + return User.findByPk(id); +}; + +const remove = async (id) => { + await User.destroy({ + where: { + id, + }, + }); +}; + +const update = async ({ id, name }) => { + await User.update({ name }, { where: { id } }); +}; + +module.exports = { + getAll, + create, + getById, + remove, + update, +}; diff --git a/src/setup.js b/src/setup.js new file mode 100644 index 00000000..b47c5911 --- /dev/null +++ b/src/setup.js @@ -0,0 +1,3 @@ +const { User } = require('./models/User.model'); + +User.sync({ force: true });