-
Notifications
You must be signed in to change notification settings - Fork 663
task #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
task #518
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,19 @@ | ||
| 'use strict'; | ||
|
|
||
| const express = require('express'); | ||
| const usersRouter = require('./routes/users'); | ||
| const expensesRouter = require('./routes/expenses'); | ||
| const categoriesRouter = require('./routes/categories'); | ||
|
|
||
| const createServer = () => { | ||
| // your code goes here | ||
| const app = express(); | ||
|
|
||
| app.use(express.json()); | ||
| app.use('/users', usersRouter); | ||
| app.use('/expenses', expensesRouter); | ||
|
Comment on lines
+12
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The task requires a CRUD page to manage categories. There is no categories router mounted here. Add and mount a categories router (for example |
||
| app.use('/categories', categoriesRouter); | ||
|
|
||
| return app; | ||
| }; | ||
|
|
||
| module.exports = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,12 +21,12 @@ const { | |
| */ | ||
|
|
||
| const sequelize = new Sequelize({ | ||
| database: POSTGRES_DB || 'postgres', | ||
| username: POSTGRES_USER || 'postgres', | ||
| host: POSTGRES_HOST || 'localhost', | ||
| database: POSTGRES_DB || 'mydb', | ||
| username: POSTGRES_USER || 'mykola', | ||
| host: POSTGRES_HOST || '20.160.160.166', | ||
| dialect: 'postgres', | ||
| port: POSTGRES_PORT || 5432, | ||
| password: POSTGRES_PASSWORD || '123', | ||
| password: POSTGRES_PASSWORD || 'strongpassword', | ||
|
Comment on lines
+26
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The model currently defines |
||
| }); | ||
|
|
||
| module.exports = { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| 'use strict'; | ||
|
|
||
| const { sequelize } = require('../db.js'); | ||
| const { DataTypes } = require('sequelize'); | ||
|
|
||
| const Category = sequelize.define( | ||
| 'Category', | ||
| { | ||
| name: { | ||
| type: DataTypes.STRING, | ||
| allowNull: false, | ||
| }, | ||
| }, | ||
| { | ||
| tableName: 'categories', | ||
| timestamps: false, | ||
| }, | ||
| ); | ||
|
|
||
| module.exports = { | ||
| Category, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,10 +2,54 @@ | |
|
|
||
| const { sequelize } = require('../db.js'); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In createServer.js you import users and expenses routers but there is no import for a categories router. The task requires implementing a CRUD page to manage categories — add a categories router (e.g. |
||
| const { DataTypes } = require('sequelize'); | ||
|
|
||
| const Expense = sequelize.define( | ||
| // your code goes here | ||
| 'Expense', | ||
| { | ||
| userId: { | ||
| type: DataTypes.INTEGER, | ||
| allowNull: false, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You register |
||
| }, | ||
| spentAt: { | ||
| type: DataTypes.DATE, | ||
| allowNull: false, | ||
| }, | ||
| title: { | ||
| type: DataTypes.STRING, | ||
| allowNull: false, | ||
| }, | ||
| amount: { | ||
| type: DataTypes.FLOAT, | ||
| allowNull: false, | ||
| }, | ||
| categoryId: { | ||
| type: DataTypes.INTEGER, | ||
| allowNull: true, | ||
| }, | ||
| category: { | ||
| type: DataTypes.STRING, | ||
| allowNull: true, | ||
| }, | ||
| note: { | ||
| type: DataTypes.STRING, | ||
| allowNull: true, | ||
| }, | ||
| }, | ||
| { | ||
| tableName: 'expenses', | ||
| timestamps: false, | ||
| }, | ||
| ); | ||
|
|
||
| Expense.prototype.toJSON = function () { | ||
| const values = { ...this.get() }; | ||
|
|
||
| delete values.categoryId; | ||
|
|
||
| return values; | ||
| }; | ||
|
|
||
| module.exports = { | ||
| Expense, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,8 +2,20 @@ | |
|
|
||
| const { sequelize } = require('../db.js'); | ||
|
|
||
| const { DataTypes } = require('sequelize'); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| const User = sequelize.define( | ||
| // your code goes here | ||
| 'User', | ||
| { | ||
| name: { | ||
| type: DataTypes.STRING, | ||
| allowNull: false, | ||
| }, | ||
| }, | ||
| { | ||
| tableName: 'users', | ||
| timestamps: false, | ||
| }, | ||
| ); | ||
|
|
||
| module.exports = { | ||
|
Comment on lines
+11
to
21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,10 +2,18 @@ | |
|
|
||
| const { User } = require('./User.model'); | ||
| const { Expense } = require('./Expense.model'); | ||
| const { Category } = require('./Category.model'); | ||
|
|
||
| User.hasMany(Expense, { foreignKey: 'userId', constraints: false }); | ||
| Expense.belongsTo(User, { foreignKey: 'userId', constraints: false }); | ||
|
Comment on lines
+5
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You import |
||
|
|
||
| Category.hasMany(Expense, { foreignKey: 'categoryId', constraints: false }); | ||
| Expense.belongsTo(Category, { foreignKey: 'categoryId', constraints: false }); | ||
|
|
||
| module.exports = { | ||
| models: { | ||
| User, | ||
| Expense, | ||
| Category, | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| 'use strict'; | ||
|
|
||
| const express = require('express'); | ||
| const { | ||
| models: { Category }, | ||
| } = require('../models/models'); | ||
|
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You import only |
||
|
|
||
| const router = express.Router(); | ||
|
|
||
| router.post('/', async (req, res) => { | ||
| const { name } = req.body; | ||
|
|
||
| if (!name) { | ||
| return res.status(400).json({ error: 'Missing required parameter: name' }); | ||
| } | ||
|
|
||
| try { | ||
| const category = await Category.create({ name }); | ||
|
|
||
| res.status(201).json(category); | ||
| } catch (error) { | ||
| res.status(500).json({ error: error.message }); | ||
|
Comment on lines
+11
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This |
||
| } | ||
| }); | ||
|
|
||
| router.get('/', async (req, res) => { | ||
| const categories = await Category.findAll(); | ||
|
|
||
|
Comment on lines
+26
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The categories filter is mapped to numbers and NaNs are removed, so non-numeric category names (strings) will be ignored. If you intend to support filtering by category name (allowed by the task as an option), map provided names to Category ids before building the |
||
| res.status(200).json(categories); | ||
| }); | ||
|
|
||
| router.get('/:id', async (req, res) => { | ||
| const { id } = req.params; | ||
| const category = await Category.findByPk(id); | ||
|
|
||
| if (!category) { | ||
| return res.status(404).json({ error: 'Category not found' }); | ||
| } | ||
| res.status(200).json(category); | ||
| }); | ||
|
|
||
| router.delete('/:id', async (req, res) => { | ||
| const { id } = req.params; | ||
| const category = await Category.findByPk(id); | ||
|
|
||
| if (!category) { | ||
| return res.status(404).json({ error: 'Category not found' }); | ||
|
Comment on lines
+46
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GET /expenses currently filters with |
||
| } | ||
| await category.destroy(); | ||
| res.status(204).send(); | ||
| }); | ||
|
|
||
| const updateHandler = async (req, res) => { | ||
|
Comment on lines
+50
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider returning expenses with their Category included ( |
||
| const { id } = req.params; | ||
| const { name } = req.body; | ||
| const category = await Category.findByPk(id); | ||
|
|
||
| if (!category) { | ||
| return res.status(404).json({ error: 'Category not found' }); | ||
| } | ||
|
|
||
| if (name !== undefined) { | ||
| category.name = name; | ||
| } | ||
|
|
||
| await category.save(); | ||
| res.status(200).json(category); | ||
| }; | ||
|
|
||
|
Comment on lines
+68
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. POST handler destructures and accepts |
||
| router.patch('/:id', updateHandler); | ||
| router.put('/:id', updateHandler); | ||
|
|
||
| module.exports = router; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Category model exists, but you must ensure associations between Category and Expense are defined (e.g.,
Category.hasMany(Expense, { foreignKey: 'categoryId', constraints: false })andExpense.belongsTo(Category, { foreignKey: 'categoryId', constraints: false })) in your central models file. Also ensure DB-level FK constraints won't prevent test truncation (useconstraints: falseor avoid DB-level FK if tests truncate tables) — this ties to checklist items #4, #5 and #7.