Skip to content
Open

test #509

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions src/controller/expenses.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const expensesServices = require('../services/expenses.services');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The imported expensesServices module still relies on an in-memory array for data storage. To meet the task requirement of using PostgreSQL, this service must be refactored to use the Expense Sequelize model for all its database operations.

const usersService = require('../services/users.services');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usersService module has incorrectly implemented methods. For example, the getUserById function used later in this file will cause the application to crash. Please fix the service to correctly use the User model for all database queries.


async function getExpenses(req, res) {
const { userId, categories, from, to } = req.query;

const expenses = await expensesServices.getExpenses({
userId: +userId,
categories,
from,
to,
});

res.send(expenses.map(expensesServices.normalize));
}

async function getExpenseById(req, res) {
const { id } = req.params;

if (!id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const expense = await expensesServices.getExpenseById(+id);

if (!expense) {
return res.status(404).json({ message: 'Not found' });
}
res.send(expensesServices.normalize(expense));
}

async function createExpense(req, res) {
const { userId, spentAt, title, amount, category, note } = req.body;

if (
userId == null ||
!spentAt ||
!title ||
amount == null ||
isNaN(+amount)
) {
return res.status(400).json({ message: 'Bad Request' });
}

const userExist = await usersService.getUserById(+userId);

if (!userExist) {
return res.status(400).json({ message: 'Bad Request' });
}

const newExpense = await expensesServices.createExpense({
userId: +userId,
spentAt,
title,
amount,
category: category || '',
note: note || '',
});

res.status(201).send(expensesServices.normalize(newExpense));
}

async function deleteExpense(req, res) {
const { id } = req.params;

if (!id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const wasDeleted = await expensesServices.deleteExpense(+id);

if (!wasDeleted) {
return res.status(404).json({ message: 'Not found' });
}
res.status(204).send();
}

async function updateExpense(req, res) {
const { id } = req.params;

if (!id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const expenseExist = await expensesServices.getExpenseById(+id);

if (!expenseExist) {
return res.status(404).json({ message: 'Not found' });
}

const { spentAt, title, amount, category, note } = req.body;

if (
spentAt === undefined &&
title === undefined &&
amount === undefined &&
category === undefined &&
note === undefined
) {
return res.status(400).json({ message: 'Bad Request' });
}

const updatedExpense = await expensesServices.updateExpense({
id: +id,
...req.body,
});

if (!updatedExpense) {
return res.status(404).json({ message: 'Not found' });
}
res.send(expensesServices.normalize(updatedExpense));
}

module.exports = {
getExpenses,
getExpenseById,
createExpense,
deleteExpense,
updateExpense,
};
73 changes: 73 additions & 0 deletions src/controller/users.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
const usersService = require('../services/users.services');

async function getUsers(req, res) {
const users = await usersService.getUsers();

res.send(users.map(usersService.normalize));
}

async function getUserById(req, res) {
const { id } = req.params;

if (!id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const user = await usersService.getUserById(+id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service method getUserById is not correctly implemented in users.services.js. It seems to be based on an in-memory array (users) that is not defined in the service file, instead of fetching data from the database. This will cause the application to crash. This function should be updated to use the User model to find a user by their ID in the database.


if (!user) {
return res.status(404).json({ message: 'Not found' });
}
res.send(usersService.normalize(user));
}

async function createUser(req, res) {
const { name } = req.body;

if (!name) {
return res.status(400).json({ message: 'Bad Request' });
}

const newUser = await usersService.createUser(name);

res.status(201).send(usersService.normalize(newUser));
}

async function deleteUser(req, res) {
const { id } = req.params;

if (!id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const wasDeleted = await usersService.deleteUser(+id);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usersService.deleteUser method is not correctly implemented in users.services.js. It's using logic for an in-memory array and will not interact with the PostgreSQL database. This should be updated to use the User model to delete the user record.


if (!wasDeleted) {
return res.status(404).json({ message: 'Not found' });
}
res.status(204).send();
}

async function updateUser(req, res) {
const { id } = req.params;
const { name } = req.body;

if (!name || !id || isNaN(+id)) {
return res.status(400).json({ message: 'Bad Request' });
}

const updatedUser = await usersService.updateUser({ id: +id, name });

if (!updatedUser) {
return res.status(404).json({ message: 'Not found' });
}
res.send(usersService.normalize(updatedUser));
}

module.exports = {
getUsers,
getUserById,
createUser,
deleteUser,
updateUser,
};
30 changes: 29 additions & 1 deletion src/createServer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
'use strict';

const express = require('express');
const { usersRouter } = require('./routers/users.router');
const cors = require('cors');
const { expensesRouter } = require('./routers/expenses.router');
const { User } = require('./models/User.model');
const { Expense } = require('./models/Expense.model');
Comment on lines +7 to +8
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're missing the import for the Category model. It needs to be imported here to be used for database synchronization.

const { sequelize } = require('./db.js');
const createServer = () => {
// your code goes here
const syncDb = async () => {
try {
await sequelize.authenticate();
await User.sync();
await Expense.sync();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The task requires a Category model. Once you've created it, you'll also need to sync it with the database here, just like you've done for User and Expense.

Comment on lines +14 to +15
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Category model also needs to be synchronized with the database. Please add await Category.sync() here.

} catch (error) {
// eslint-disable-next-line no-console
console.error('DB sync failed:', error);
}
};

syncDb();

const app = express();

app.use(cors());
app.use(express.json());

app.use('/users', usersRouter);
app.use('/expenses', expensesRouter);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle category-related requests, you need to create a router for categories and register it here, for example: app.use('/categories', categoriesRouter);.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the category management available through the API, you'll need to create a router for categories and register it here using app.use('/categories', categoriesRouter);.

Comment on lines +29 to +30
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The router for the categories feature is not registered. You need to import categoriesRouter and then use it with app.use() to expose the category endpoints.


return app;
};

module.exports = {
Expand Down
4 changes: 2 additions & 2 deletions src/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ const {
*/

const sequelize = new Sequelize({
database: POSTGRES_DB || 'postgres',
database: POSTGRES_DB || 'test',
username: POSTGRES_USER || 'postgres',
host: POSTGRES_HOST || 'localhost',
dialect: 'postgres',
port: POSTGRES_PORT || 5432,
password: POSTGRES_PASSWORD || '123',
password: POSTGRES_PASSWORD || 'password',
});

module.exports = {
Expand Down
31 changes: 30 additions & 1 deletion src/models/Expense.model.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
'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.INTEGER,
allowNull: false,
},
category: {
type: DataTypes.STRING,
allowNull: false,
},
note: {
type: DataTypes.STRING,
},
},
{
tableName: 'expenses',
},
);

module.exports = {
Expand Down
12 changes: 11 additions & 1 deletion src/models/User.model.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
'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',
},
);

module.exports = {
Expand Down
15 changes: 15 additions & 0 deletions src/routers/expenses.router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const expensesController = require('../controller/expenses.controller');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The controller used for these routes relies on a service that has not been migrated to PostgreSQL. All the expense-related operations are still using an in-memory array instead of the database.


const Router = require('express').Router;

const expensesRouter = Router();

expensesRouter.get('/', expensesController.getExpenses);
expensesRouter.get('/:id', expensesController.getExpenseById);
expensesRouter.post('/', expensesController.createExpense);
expensesRouter.delete('/:id', expensesController.deleteExpense);
expensesRouter.patch('/:id', expensesController.updateExpense);

module.exports = {
expensesRouter,
};
15 changes: 15 additions & 0 deletions src/routers/users.router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const usersController = require('../controller/users.controller');

const Router = require('express').Router;

const usersRouter = Router();

usersRouter.get('/', usersController.getUsers);
usersRouter.get('/:id', usersController.getUserById);
usersRouter.post('/', usersController.createUser);
usersRouter.delete('/:id', usersController.deleteUser);
usersRouter.patch('/:id', usersController.updateUser);

module.exports = {
usersRouter,
};
Loading
Loading