diff --git a/src/controllers/expense.controller.js b/src/controllers/expense.controller.js new file mode 100644 index 00000000..7e3a5e55 --- /dev/null +++ b/src/controllers/expense.controller.js @@ -0,0 +1,98 @@ +const expensesService = require('../services/expense.service.js'); +const userService = require('../services/user.service.js'); + +const get = async (req, res) => { + res.send(await expensesService.getAll(req.query)); +}; + +const create = async (req, res) => { + const expense = req.body; + + if (!(await userService.getById(expense.userId))) { + res.sendStatus(400); + + return; + } + + const newExpense = await expensesService.create(expense); + + res.statusCode = 201; + res.send(newExpense); +}; + +const getOne = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + const expense = await expensesService.getById(id); + + if (!expense) { + res.sendStatus(404); + + return; + } + + res.send(expense); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + if (!(await expensesService.getById(id))) { + res.sendStatus(404); + + return; + } + + await expensesService.remove(id); + res.sendStatus(204); +}; + +const update = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + const expense = await expensesService.getById(id); + + if (!expense) { + res.sendStatus(404); + + return; + } + + const data = req.body; + + if (!data) { + res.sendStatus(400); + + return; + } + + const updatedExpense = await expensesService.update(expense, data); + + 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..8e94701f --- /dev/null +++ b/src/controllers/user.controller.js @@ -0,0 +1,95 @@ +const userServices = require('../services/user.service.js'); + +const get = async (req, res) => { + res.send(await userServices.getAll()); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name) { + res.sendStatus(400); + } + + const user = await userServices.create(name); + + res.statusCode = 201; + res.send(user); +}; + +const getOne = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + const user = await userServices.getById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + res.send(user); +}; + +const remove = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + if (!(await userServices.getById(id))) { + res.sendStatus(404); + + return; + } + + await userServices.remove(id); + res.sendStatus(204); +}; + +const update = async (req, res) => { + const { id } = req.params; + + if (!id) { + res.sendStatus(400); + + return; + } + + const { name } = req.body; + + if (!name || typeof name !== 'string') { + res.sendStatus(400); + + return; + } + + const user = await userServices.getById(id); + + if (!user) { + res.sendStatus(404); + + return; + } + + const updatedUser = await userServices.update({ id, name }); + + res.send(updatedUser); +}; + +module.exports = { + get, + create, + getOne, + remove, + update, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..26fca092 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,7 +1,23 @@ 'use strict'; +const express = require('express'); +const cors = require('cors'); +const { router: userRouter } = require('./routes/user.route.js'); +const { router: expenseRouter } = require('./routes/expense.route.js'); + const createServer = () => { - // your code goes here + const app = express(); + + app.use(cors()); + + app.use('/users', express.json(), userRouter); + app.use('/expenses', express.json(), expenseRouter); + + app.use((req, res) => { + res.status(404).json({ error: 'Not found' }); + }); + + return app; }; module.exports = { diff --git a/src/db.js b/src/db.js index 1ba3046c..dc55bad5 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 || 'prosto123', }); module.exports = { diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..9a30e7cc 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,45 @@ '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.DATE, + allowNull: false, + }, + title: { + type: DataTypes.STRING, + allowNull: false, + }, + amount: { + type: DataTypes.INTEGER, + allowNull: false, + }, + category: { + type: DataTypes.STRING, + allowNull: false, + }, + note: { + type: DataTypes.STRING, + allowNull: true, + }, + }, + { + tableName: 'expenses', + timestamps: false, + }, ); module.exports = { diff --git a/src/models/User.model.js b/src/models/User.model.js index 61861c9e..83819ced 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,26 @@ 'use strict'; +const { DataTypes } = require('sequelize'); const { sequelize } = require('../db.js'); const User = sequelize.define( - // your code goes here + 'User', + { + id: { + type: DataTypes.INTEGER, + allowNull: false, + autoIncrement: true, + primaryKey: true, + }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + }, + { + tableName: 'users', + timestamps: false, + }, ); module.exports = { diff --git a/src/routes/expense.route.js b/src/routes/expense.route.js new file mode 100644 index 00000000..d7433078 --- /dev/null +++ b/src/routes/expense.route.js @@ -0,0 +1,15 @@ +const express = require('express'); +const router = express.Router(); +const expensesController = require('../controllers/expense.controller.js'); + +router.get('/', expensesController.get); + +router.post('/', expensesController.create); + +router.get('/:id', expensesController.getOne); + +router.delete('/:id', expensesController.remove); + +router.patch('/:id', expensesController.update); + +module.exports = { router }; diff --git a/src/routes/user.route.js b/src/routes/user.route.js new file mode 100644 index 00000000..5d6bbf8a --- /dev/null +++ b/src/routes/user.route.js @@ -0,0 +1,15 @@ +const express = require('express'); +const router = express.Router(); +const userController = require('../controllers/user.controller.js'); + +router.get('/', userController.get); + +router.post('/', userController.create); + +router.get('/:id', userController.getOne); + +router.delete('/:id', userController.remove); + +router.patch('/:id', userController.update); + +module.exports = { router }; diff --git a/src/services/expense.service.js b/src/services/expense.service.js new file mode 100644 index 00000000..e9e3a46b --- /dev/null +++ b/src/services/expense.service.js @@ -0,0 +1,83 @@ +const { + models: { Expense }, +} = require('../models/models'); +const { Op } = require('sequelize'); + +const getAll = async (userId, categories, from, to) => { + const where = {}; + + if (userId) { + where.userId = userId; + } + + if (categories) { + where.category = categories; + } + + if (from || to) { + where.spentAt = { + [Op.between]: [from || new Date(0), to || new Date()], + }; + } + + return Expense.findAll({ where }); +}; + +const getById = async (id) => { + return Expense.findByPk(id); +}; + +const create = async ({ userId, spentAt, title, amount, category, note }) => { + return Expense.create({ + userId, + spentAt, + title, + amount, + category, + note, + }); +}; + +const remove = async (id) => { + await Expense.destroy({ where: { id } }); +}; + +const update = async (id, { spentAt, title, amount, category, note }) => { + const expense = await Expense.findByPk(id); + + if (!expense) { + return null; + } + + if (spentAt) { + expense.spentAt = spentAt; + } + + if (title) { + expense.title = title; + } + + if (amount) { + expense.amount = amount; + } + + if (category) { + expense.category = category; + } + + if (note) { + expense.note = note; + } + + await expense.save(); + + return expense; +}; + +module.exports = { + getAll, + getById, + create, + remove, + update, +}; diff --git a/src/services/user.service.js b/src/services/user.service.js new file mode 100644 index 00000000..6a4fb51b --- /dev/null +++ b/src/services/user.service.js @@ -0,0 +1,37 @@ +const { + models: { User }, +} = require('../models/models'); + +const getAll = async () => { + return User.findAll(); +}; + +const getById = async (id) => { + return User.findByPk(id); +}; + +const create = async (name) => { + return User.create({ name }); +}; + +const remove = async (id) => { + await User.destroy({ + where: { + id, + }, + }); +}; + +const update = async ({ id, name }) => { + await User.update({ name }, { where: id }); + + return User.findByPk(id); +}; + +module.exports = { + getAll, + getById, + create, + remove, + update, +};