From a442fc08b5ee4f2525eb3a9d457b70d5d01157c7 Mon Sep 17 00:00:00 2001 From: eduvinagre Date: Thu, 11 Jul 2024 00:17:01 -0300 Subject: [PATCH] adding task solution --- src/controllers/expenseController.js | 117 +++++++++++++++++++++++++++ src/controllers/userController.js | 90 +++++++++++++++++++++ src/createServer.js | 16 +++- src/db.js | 4 +- src/index.js | 13 +++ src/models/Expense.model.js | 32 +++++++- src/models/User.model.js | 18 ++++- src/routes/expenseRoutes.js | 14 ++++ src/routes/userRoutes.js | 14 ++++ src/services/expenseService.js | 64 +++++++++++++++ src/services/userService.js | 48 +++++++++++ 11 files changed, 423 insertions(+), 7 deletions(-) create mode 100644 src/controllers/expenseController.js create mode 100644 src/controllers/userController.js create mode 100644 src/routes/expenseRoutes.js create mode 100644 src/routes/userRoutes.js create mode 100644 src/services/expenseService.js create mode 100644 src/services/userService.js diff --git a/src/controllers/expenseController.js b/src/controllers/expenseController.js new file mode 100644 index 00000000..ec059e09 --- /dev/null +++ b/src/controllers/expenseController.js @@ -0,0 +1,117 @@ +/* eslint-disable no-console */ +'use strict'; + +const { ExpenseService } = require('../services/expenseService'); +const expenseService = new ExpenseService(); +const userService = require('../services/userService'); + +async function createExpense(req, res) { + try { + const { userId, spentAt, title, amount, category, note } = req.body; + + if (!spentAt || !title || !amount || !userId) { + return res.status(400).send('All fields are required'); + } + + const user = await userService.getAllUsers({ id: userId }); + + if (user.length === 0) { + return res.status(400).send('Bad Request'); + } + + const newExpense = await expenseService.createExpense( + userId, + spentAt, + title, + amount, + category, + note, + ); + + res.status(201).json(newExpense); + } catch (error) { + console.error(error); + res.status(500).send('Error creating expense'); + } +} + +async function getAllExpenses(req, res) { + try { + const userId = req.query.userId; + const category = req.query.categories; + const filters = {}; + + if (userId) { + filters.userId = userId; + } + + if (category) { + filters.category = category; + } + + const expenses = await expenseService.getAllExpenses(filters); + + res.json(expenses); + } catch (error) { + console.error(error); + res.status(500).send('Error getting expenses'); + } +} + +async function getExpense(req, res) { + try { + const [expense] = await expenseService.getAllExpenses({ + id: parseInt(req.params.id), + }); + + if (!expense) { + return res.status(404).send('Expense not found'); + } + + res.json(expense); + } catch (error) { + console.error(error); + res.status(500).send('Error getting expense'); + } +} + +async function updateExpense(req, res) { + try { + const expense = await expenseService.updateExpense( + parseInt(req.params.id), + req.body, + ); + + if (!expense) { + return res.status(404).send('Expense not found'); + } + + res.json(expense); + } catch (error) { + console.error(error); + res.status(500).send('Error updating expense'); + } +} + +async function deleteExpense(req, res) { + try { + const success = await expenseService.deleteExpense(parseInt(req.params.id)); + + if (!success) { + return res.status(404).send('Expense not found'); + } + + res.status(204).send(); + } catch (error) { + console.error(error); + res.status(500).send('Error deleting expense'); + } +} + +module.exports = { + createExpense, + getAllExpenses, + getExpense, + updateExpense, + deleteExpense, +}; diff --git a/src/controllers/userController.js b/src/controllers/userController.js new file mode 100644 index 00000000..759c145e --- /dev/null +++ b/src/controllers/userController.js @@ -0,0 +1,90 @@ +'use strict'; + +const userService = require('../services/userService'); + +async function createUser(req, res) { + const { name } = req.body; + + if (!name) { + return res.status(400).send('Name and are required'); + } + + try { + const newUser = await userService.createUser({ name }); + + res.status(201).json(newUser); + } catch (error) { + res.status(500).send('Error creating user'); + } +} + +async function getAllUsers(req, res) { + try { + const users = await userService.getAllUsers(req.query); + + res.json(users); + } catch (error) { + res.status(500).send('Error fetching users'); + } +} + +async function getUser(req, res) { + try { + const users = await userService.getAllUsers({ + id: parseInt(req.params.id), + }); + const user = users[0]; + + if (!user) { + return res.status(404).send('User not found'); + } + + res.json(user); + } catch (error) { + res.status(500).send('Error fetching user'); + } +} + +async function updateUser(req, res) { + const { name } = req.body; + + if (!name) { + return res.status(400).send('Name and are required'); + } + + try { + const user = await userService.updateUser(parseInt(req.params.id), { + name, + }); + + if (!user) { + return res.status(404).send('User not found'); + } + + res.json(user); + } catch (error) { + res.status(500).send('Error updating user'); + } +} + +async function deleteUser(req, res) { + try { + const success = await userService.deleteUser(parseInt(req.params.id)); + + if (!success) { + return res.status(404).send('User not found'); + } + + res.status(204).send(); + } catch (error) { + res.status(500).send('Error deleting user'); + } +} + +module.exports = { + createUser, + getAllUsers, + getUser, + updateUser, + deleteUser, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..e740f697 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,18 @@ 'use strict'; -const createServer = () => { - // your code goes here -}; +const express = require('express'); +const userRoutes = require('./routes/userRoutes'); +const expenseRoutes = require('./routes/expenseRoutes'); + +function createServer() { + const app = express(); + + app.use(express.json()); + app.use('/users', userRoutes); + app.use('/expenses', expenseRoutes); + + return app; +} module.exports = { createServer, diff --git a/src/db.js b/src/db.js index 1ba3046c..40e8b05a 100644 --- a/src/db.js +++ b/src/db.js @@ -16,7 +16,7 @@ const { } = process.env; /* - All credentials setted to default values (exsept password - it is exapmle) + All credentials set to default values (except password - it is example) replace if needed with your own */ @@ -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 || 'yasmart', }); module.exports = { diff --git a/src/index.js b/src/index.js index 54173732..511dfcc7 100644 --- a/src/index.js +++ b/src/index.js @@ -2,8 +2,21 @@ 'use strict'; +const { sequelize } = require('./db'); + const { createServer } = require('./createServer'); createServer().listen(5700, () => { console.log('Server is running on localhost:5700'); }); + +(async () => { + try { + await sequelize.sync({ force: true }); + console.log('Database synchronized'); + } catch (error) { + console.error('Unable to synchronize the database:', error); + } finally { + await sequelize.close(); + } +})(); diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..c2e80ff4 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,39 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const Expense = sequelize.define( - // your code goes here + 'Expense', + { + userId: { + type: DataTypes.INTEGER, + allowNull: false, + }, + spentAt: { + type: DataTypes.DATE, + allowNull: false, + }, + title: { + type: DataTypes.STRING, + allowNull: false, + }, + amount: { + type: DataTypes.FLOAT, + allowNull: false, + }, + category: { + type: DataTypes.STRING, + allowNull: true, + }, + note: { + type: DataTypes.STRING, + allowNull: true, + }, + }, + { + timestamps: false, + }, ); module.exports = { diff --git a/src/models/User.model.js b/src/models/User.model.js index 61861c9e..2dc8dceb 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,25 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const User = sequelize.define( - // your code goes here + 'User', + { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + tableName: 'users', + timestamps: false, + }, ); module.exports = { diff --git a/src/routes/expenseRoutes.js b/src/routes/expenseRoutes.js new file mode 100644 index 00000000..086f8ee8 --- /dev/null +++ b/src/routes/expenseRoutes.js @@ -0,0 +1,14 @@ +'use strict'; + +const express = require('express'); +const expenseController = require('../controllers/expenseController'); + +const router = express.Router(); + +router.post('/', expenseController.createExpense); +router.get('/', expenseController.getAllExpenses); +router.get('/:id', expenseController.getExpense); +router.patch('/:id', expenseController.updateExpense); +router.delete('/:id', expenseController.deleteExpense); + +module.exports = router; diff --git a/src/routes/userRoutes.js b/src/routes/userRoutes.js new file mode 100644 index 00000000..44288198 --- /dev/null +++ b/src/routes/userRoutes.js @@ -0,0 +1,14 @@ +'use strict'; + +const express = require('express'); +const userController = require('../controllers/userController'); + +const router = express.Router(); + +router.post('/', userController.createUser); +router.get('/', userController.getAllUsers); +router.get('/:id', userController.getUser); +router.patch('/:id', userController.updateUser); +router.delete('/:id', userController.deleteUser); + +module.exports = router; diff --git a/src/services/expenseService.js b/src/services/expenseService.js new file mode 100644 index 00000000..913849af --- /dev/null +++ b/src/services/expenseService.js @@ -0,0 +1,64 @@ +'use strict'; + +const { models } = require('../models/models'); + +class ExpenseService { + async createExpense(userId, spentAt, title, amount, category, note) { + try { + const newExpense = await models.Expense.create({ + userId, + spentAt, + title, + amount, + category, + note, + }); + + return newExpense; + } catch (error) { + throw error; + } + } + + async getAllExpenses(filters = {}) { + try { + const expenses = await models.Expense.findAll({ + where: filters, + }); + + return expenses; + } catch (error) { + throw error; + } + } + + async updateExpense(id, newExpense) { + try { + const [updatedRowsCount, [updatedExpense]] = await models.Expense.update( + newExpense, + { + where: { id }, + returning: true, + }, + ); + + return updatedRowsCount ? updatedExpense : null; + } catch (error) { + throw error; + } + } + + async deleteExpense(id) { + try { + const deletedRowsCount = await models.Expense.destroy({ + where: { id }, + }); + + return deletedRowsCount > 0; + } catch (error) { + throw error; + } + } +} + +module.exports = { ExpenseService }; diff --git a/src/services/userService.js b/src/services/userService.js new file mode 100644 index 00000000..0768ef2d --- /dev/null +++ b/src/services/userService.js @@ -0,0 +1,48 @@ +'use strict'; + +const { User } = require('../models/User.model'); + +const userService = { + async createUser({ name }) { + const newUser = await User.create({ name }); + + return newUser; + }, + + async getAllUsers(filters = {}) { + const where = {}; + + if (filters.id) { + where.id = filters.id; + } + + if (filters.name) { + where.name = filters.name; + } + + const users = await User.findAll({ where }); + + return users; + }, + + async updateUser(id, { name }) { + const user = await User.findByPk(id); + + if (user) { + user.name = name; + await user.save(); + + return user; + } + + return null; + }, + + async deleteUser(id) { + const result = await User.destroy({ where: { id } }); + + return result > 0; + }, +}; + +module.exports = userService;