From 8cb6fd59d35cf505b5582ada6b9668584d31f1b2 Mon Sep 17 00:00:00 2001 From: Vlad Gerula Date: Tue, 19 Mar 2024 20:15:12 +0200 Subject: [PATCH] add solution with DB --- .gitignore | 2 - package-lock.json | 237 ++++++++++++++++++++----- package.json | 2 +- src/constants.js | 13 ++ src/controllers/expenses.controller.js | 90 ++++++++++ src/controllers/user.controller.js | 80 +++++++++ src/createServer.js | 17 +- src/db.js | 2 +- src/models/Expense.model.js | 45 ++++- src/models/User.model.js | 21 ++- src/routes/expenses.route.js | 16 ++ src/routes/user.route.js | 16 ++ src/services/expenses.service.js | 60 +++++++ src/services/users.service.js | 39 ++++ 14 files changed, 582 insertions(+), 58 deletions(-) create mode 100644 src/constants.js create mode 100644 src/controllers/expenses.controller.js create mode 100644 src/controllers/user.controller.js create mode 100644 src/routes/expenses.route.js create mode 100644 src/routes/user.route.js create mode 100644 src/services/expenses.service.js create mode 100644 src/services/users.service.js diff --git a/.gitignore b/.gitignore index d7267872..bd6a178a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,3 @@ node_modules # MacOS .DS_Store - -.env.local diff --git a/package-lock.json b/package-lock.json index 404fbb0b..f3f66f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1048,9 +1048,9 @@ } }, "@mate-academy/scripts": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.7.3.tgz", - "integrity": "sha512-5cqlZbgbwIxiicQsjP7OR0cR/QBZTipfe4Eh/6VLn0dvP9yAhnZBu3ZN3PjS/1swlVthnIFrNL7xzU4gbPu3dQ==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@mate-academy/scripts/-/scripts-1.7.8.tgz", + "integrity": "sha512-AgOZbcf1G01D4JXPF+lm55zmv4HBE/h6rGIKuHDUNYx4owWqPE49XX8k2lkEdGP8muG8RxQ1DYvjQg+sYqPluA==", "dev": true, "requires": { "@octokit/rest": "^17.11.2", @@ -1639,19 +1639,6 @@ "is-string": "^1.0.7" } }, - "array.prototype.filter": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.3.tgz", - "integrity": "sha512-VizNcj/RGJiUyQBgzwxzE5oHdeuXY5hSbbmKMlphj1cy1Vl7Pn2asCGbSrru6hSQjmCzqTBPVWAF/whmEOVHbw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, "array.prototype.findlastindex": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.4.tgz", @@ -2190,6 +2177,39 @@ } } }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2402,12 +2422,6 @@ "which-typed-array": "^1.1.14" } }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, "es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -2421,6 +2435,15 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, "es-set-tostringtag": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", @@ -3469,6 +3492,15 @@ "hasown": "^2.0.0" } }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "requires": { + "is-typed-array": "^1.1.13" + } + }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -4670,27 +4702,81 @@ } }, "object.groupby": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.2.tgz", - "integrity": "sha512-bzBq58S+x+uo0VjurFT0UktpKHOZmv4/xePiOA1nbB9pMqpGK7rUPNgf+1YC+7mE+0HzhTMqNUuCqvKhj6FnBw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "requires": { - "array.prototype.filter": "^1.0.3", - "call-bind": "^1.0.5", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.0.0" + "es-abstract": "^1.23.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + } } }, "object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "on-finished": { @@ -5485,25 +5571,82 @@ } }, "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.2.tgz", + "integrity": "sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + } } }, "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { diff --git a/package.json b/package.json index 1ab6934a..f62af979 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@mate-academy/eslint-config": "latest", - "@mate-academy/scripts": "^1.7.3", + "@mate-academy/scripts": "^1.7.8", "axios": "^1.6.7", "eslint": "^7.32.0", "eslint-plugin-jest": "^22.4.1", diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 00000000..393f0105 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,13 @@ +'use strict'; + +const NOT_FOUND = 404; +const BAD_REQUEST = 400; +const NO_CONTENT = 204; +const CREATED = 201; + +module.exports = { + NOT_FOUND, + BAD_REQUEST, + NO_CONTENT, + CREATED, +}; diff --git a/src/controllers/expenses.controller.js b/src/controllers/expenses.controller.js new file mode 100644 index 00000000..09621831 --- /dev/null +++ b/src/controllers/expenses.controller.js @@ -0,0 +1,90 @@ +'use strict'; + +const expenseService = require('../services/expenses.service'); +const { getUserById } = require('../services/users.service'); +const { NOT_FOUND, BAD_REQUEST, NO_CONTENT, CREATED } = require('../constants'); + +const getAll = async (req, res) => { + const { userId, categories, from, to } = req.query; + + res.send(await expenseService.getAllExpenses(userId, categories, from, to)); +}; + +const getOneById = async (req, res) => { + const { id } = req.params; + const expense = await expenseService.getExpenseById(+id); + + if (!expense) { + res.status(NOT_FOUND).send(); + + return; + } + + res.send(expense); +}; + +const create = async (req, res) => { + const newExpense = req.body; + const { userId } = req.body; + + const existUser = await getUserById(userId); + + if (!existUser) { + return res.status(BAD_REQUEST).send(); + } + + const createdExpense = await expenseService.createExpense(newExpense); + + res.status(CREATED).send(createdExpense); +}; + +const update = async (req, res) => { + const { id } = req.params; + const newExpense = req.body; + + if (!newExpense) { + res.sendStatus(BAD_REQUEST); + + return; + } + + const expense = await expenseService.getExpenseById(id); + + if (!expense) { + res.status(NOT_FOUND).send(); + + return; + } + + const updatedExpense = await expenseService.updateExpense(id, newExpense); + + if (!updatedExpense) { + res.status(NOT_FOUND).send(); + + return; + } + + res.send(updatedExpense); +}; + +const remove = async (req, res) => { + const { id } = req.params; + const expense = await expenseService.getExpenseById(id); + + if (!expense) { + res.status(NOT_FOUND).send(); + + return; + } + + await expenseService.removeExpense(+id); + res.status(NO_CONTENT).send(); +}; + +module.exports = { + getAll, + getOneById, + create, + update, + remove, +}; diff --git a/src/controllers/user.controller.js b/src/controllers/user.controller.js new file mode 100644 index 00000000..8efcf3d3 --- /dev/null +++ b/src/controllers/user.controller.js @@ -0,0 +1,80 @@ +'use strict'; + +const { NOT_FOUND, BAD_REQUEST, NO_CONTENT, CREATED } = require('../constants'); + +const userService = require('../services/users.service'); + +const getAll = async (req, res) => { + res.send(await userService.getAllUsers()); +}; + +const getOneUser = async (req, res) => { + const { id } = req.params; + + const user = await userService.getUserById(id); + + if (!user) { + res.status(NOT_FOUND).send(); + + return; + } + + res.send(user); +}; + +const create = async (req, res) => { + const { name } = req.body; + + if (!name || typeof name !== 'string') { + res.status(BAD_REQUEST).send(); + + return; + } + + const user = await userService.createUser(name); + + res.status(CREATED).send(user); +}; + +const update = async (req, res) => { + const { name } = req.body; + const { id } = req.params; + + if (!name || !id || typeof name !== 'string') { + res.sendStatus(BAD_REQUEST); + } + + const user = await userService.getUserById(id); + + if (!user) { + res.sendStatus(NOT_FOUND); + + return; + } + + const updatedUser = await userService.updateUser(id, name); + + res.send(updatedUser); +}; + +const remove = async (req, res) => { + const { id } = req.params; + const user = await userService.getUserById(id); + + if (!user) { + res.status(NOT_FOUND).send(); + + return; + } + + await userService.removeUser(+id); + res.status(NO_CONTENT).send(); +}; + +module.exports = { + getAll, + getOneUser, + create, + update, + remove, +}; diff --git a/src/createServer.js b/src/createServer.js index 1ea5542d..c8338ae2 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,8 +1,17 @@ -'use strict'; +const cors = require('cors'); +const express = require('express'); +const { userRouter } = require('./routes/user.route'); +const { expenseRouter } = require('./routes/expenses.route'); +const app = express(); -const createServer = () => { - // your code goes here -}; +function createServer() { + app.use(cors()); + + app.use('/users', express.json(), userRouter); + app.use('/expenses', express.json(), expenseRouter); + + return app; +} module.exports = { createServer, diff --git a/src/db.js b/src/db.js index 1ba3046c..737d9ccc 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 || '123123', }); module.exports = { diff --git a/src/models/Expense.model.js b/src/models/Expense.model.js index 567e1c3e..abcf8b3f 100644 --- a/src/models/Expense.model.js +++ b/src/models/Expense.model.js @@ -1,9 +1,52 @@ 'use strict'; const { sequelize } = require('../db.js'); +const { DataTypes } = require('sequelize'); 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, + 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..4c16048d 100644 --- a/src/models/User.model.js +++ b/src/models/User.model.js @@ -1,9 +1,26 @@ 'use strict'; const { sequelize } = require('../db.js'); - +const { DataTypes } = require('sequelize'); 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', + createdAt: false, + updatedAt: false, + }, ); module.exports = { diff --git a/src/routes/expenses.route.js b/src/routes/expenses.route.js new file mode 100644 index 00000000..f6ba87d9 --- /dev/null +++ b/src/routes/expenses.route.js @@ -0,0 +1,16 @@ +'use strict'; + +const express = require('express'); +const expenseController = require('../controllers/expenses.controller'); + +const expenseRouter = express.Router(); + +expenseRouter.get('/', expenseController.getAll); +expenseRouter.get('/:id', expenseController.getOneById); +expenseRouter.post('/', expenseController.create); +expenseRouter.patch('/:id', expenseController.update); +expenseRouter.delete('/:id', expenseController.remove); + +module.exports = { + expenseRouter, +}; diff --git a/src/routes/user.route.js b/src/routes/user.route.js new file mode 100644 index 00000000..f7a0f9fc --- /dev/null +++ b/src/routes/user.route.js @@ -0,0 +1,16 @@ +'use strict'; + +const express = require('express'); +const userController = require('../controllers/user.controller'); + +const userRouter = express.Router(); + +userRouter.get('/', userController.getAll); +userRouter.get('/:id', userController.getOneUser); +userRouter.post('/', userController.create); +userRouter.patch('/:id', userController.update); +userRouter.delete('/:id', userController.remove); + +module.exports = { + userRouter, +}; diff --git a/src/services/expenses.service.js b/src/services/expenses.service.js new file mode 100644 index 00000000..e580f43d --- /dev/null +++ b/src/services/expenses.service.js @@ -0,0 +1,60 @@ +/* eslint-disable prettier/prettier */ +'use strict'; + +const { Expense } = require('../models/Expense.model'); + +const getAllExpenses = async (userId, categories, from, to) => { + let filteredExpenses = await Expense.findAll(); + + if (userId) { + filteredExpenses = filteredExpenses.filter( + (expense) => expense.userId === +userId, + ); + } + + if (categories && categories.length > 0) { + filteredExpenses = filteredExpenses.filter((expense) => + categories.includes(expense.category)); + } + + if (from && to) { + filteredExpenses = filteredExpenses.filter( + (expense) => + new Date(expense.spentAt) >= new Date(from) && + new Date(expense.spentAt) <= new Date(to), + ); + } + + return filteredExpenses; +}; + +const getExpenseById = async (id) => { + const expense = await Expense.findByPk(id); + + return expense; +}; + +const createExpense = async (newExpense) => { + const createdExpense = await Expense.create(newExpense); + + return createdExpense; +}; + +const updateExpense = async (id, updatedData) => { + await Expense.update(updatedData, { where: { id } }); + + // eslint-disable-next-line no-return-await + return await Expense.findByPk(id); +}; + +const removeExpense = async (id) => { + await Expense.destroy({ where: { id } }); +}; + +module.exports = { + getAllExpenses, + getExpenseById, + createExpense, + updateExpense, + removeExpense, +}; diff --git a/src/services/users.service.js b/src/services/users.service.js new file mode 100644 index 00000000..4e0e99b9 --- /dev/null +++ b/src/services/users.service.js @@ -0,0 +1,39 @@ +'use strict'; + +const { User } = require('../models/User.model'); + +const getAllUsers = async () => { + const user = await User.findAll(); + + return user; +}; + +const getUserById = async (id) => { + const user = await User.findByPk(id); + + return user; +}; + +const createUser = async (name) => { + const user = await User.create({ name }); + + return user; +}; + +const updateUser = async (id, newName) => { + await User.update({ name: newName }, { where: { id } }); + + return User.findByPk(id); +}; + +const removeUser = async (id) => { + return User.destroy({ where: { id } }); +}; + +module.exports = { + getAllUsers, + getUserById, + createUser, + updateUser, + removeUser, +};