diff --git a/src/controllers/expenses.controllers.js b/src/controllers/expenses.controllers.js new file mode 100644 index 00000000..bb9b8332 --- /dev/null +++ b/src/controllers/expenses.controllers.js @@ -0,0 +1,76 @@ +const expensesService = require('../services/expenses.services'); +const { statusCode } = require('../helpers/statusCode'); + +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(statusCode.NOT_FOUND); + + 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(statusCode.BAD_REQUEST); + + return; + } + + const expense = await expensesService.add(body); + + res.statusCode = statusCode.CREATED; + res.send(expense); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + try { + await expensesService.remove(id); + + res.sendStatus(statusCode.NO_CONTENT); + } catch (error) { + res.sendStatus(statusCode.NOT_FOUND); + } +}; + +const update = async (req, res) => { + const { id } = req.params; + const body = req.body; + const expense = await expensesService.getById(id); + + if (!expense) { + res.sendStatus(statusCode.NOT_FOUND); + + return; + } + + const updatedExpense = await expensesService.update(expense.id, body); + + res.statusCode = statusCode.OK; + 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..00273c03 --- /dev/null +++ b/src/controllers/user.controllers.js @@ -0,0 +1,83 @@ +const userService = require('../services/user.services'); +const { statusCode } = require('../helpers/statusCode'); + +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(statusCode.NOT_FOUND); + + return; + } + + res.status(statusCode.OK).send(user); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name) { + res.sendStatus(statusCode.BAD_REQUEST); + + return; + } + + const user = await userService.create(name); + + res.status(statusCode.CREATED).send(user); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + const user = await userService.getUserById(id); + + if (!user) { + res.sendStatus(statusCode.NOT_FOUND); + + return; + } + + userService.remove(id); + + res.sendStatus(statusCode.NO_CONTENT); +}; + +const update = async (req, res) => { + const { id } = req.params; + const { name } = req.body; + + const user = userService.getUserById(id); + + if (!user) { + res.sendStatus(statusCode.NOT_FOUND); + + return; + } + + if (typeof name !== 'string') { + res.sendStatus(statusCode.UNPROCESSABLE_ENTITY); + + 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/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 }; 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, +};