Commit 3be0edb2 authored by Phạm Quang Bảo's avatar Phạm Quang Bảo

feat: add fillter classes for method get

parent 38e7d8fd
...@@ -3,13 +3,21 @@ ...@@ -3,13 +3,21 @@
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"author": "PhamQuangBao", "author": "PhamQuangBao",
"type": "commonjs",
"main": "./src/index.ts", "main": "./src/index.ts",
"scripts": { "scripts": {
"dev": "tsx watch ./src/index.ts", "dev": "tsx watch ./src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"gen:db": "sequelize-auto -h localhost -d challenge_db -u postgres -x 123456 -p 2550 --dialect postgres --lang ts -o ./src/models", "gen:db": "sequelize-auto -h localhost -d challenge_db -u postgres -x 123456 -p 2550 --dialect postgres --lang ts -o ./src/models --caseProp s --useDefine",
"gen:swagger": "tsx src/scripts/swagger-gen.ts" "gen:swagger": "tsx src/scripts/swagger-gen.ts"
}, },
"imports": {
"#models/*": "./src/models/*",
"#controllers/*": "./src/controllers/*",
"#services/*": "./src/services/*",
"#providers/*": "./src/providers/*",
"#docs/*": "./src/docs/*"
},
"dependencies": { "dependencies": {
"express": "^5.2.1", "express": "^5.2.1",
"express-automatic-routes": "^1.1.0", "express-automatic-routes": "^1.1.0",
......
...@@ -11,11 +11,14 @@ export default (_express: Application) => { ...@@ -11,11 +11,14 @@ export default (_express: Application) => {
* /api/v1.0/classes: * /api/v1.0/classes:
* get: * get:
* tags: [Classes] * tags: [Classes]
* summary: Lấy danh sách lớp học * parameters:
* description: Trả về danh sách lớp học. * - $ref: '#/components/parameters/filters'
* - $ref: '#/components/parameters/sort'
* - $ref: '#/components/parameters/page'
* - $ref: '#/components/parameters/pageSize'
* responses: * responses:
* 200: * 200:
* description: Trả về danh sách lớp học thành công * description: Trả về danh sách lớp học thành công
* content: * content:
* application/json: * application/json:
* schema: * schema:
...@@ -25,8 +28,23 @@ export default (_express: Application) => { ...@@ -25,8 +28,23 @@ export default (_express: Application) => {
*/ */
get: { get: {
handler: async (req, res) => { handler: async (req, res) => {
const classes = await classesProvider.getAllClasses(); try {
return res.json(classes); // 1. Lấy các tham số từ Query String (được Swagger gửi lên)
const { filters, sort, page, pageSize } = req.query;
// 2. Truyền các tham số này vào hàm xử lý
const classes = await classesProvider.getAllClasses({
filters: filters as string,
sort: sort as string,
page: page ? parseInt(page as string) : 1,
pageSize: pageSize ? parseInt(pageSize as string) : 10
});
return res.json(classes);
} catch (error) {
console.error('Error getting classes:', error);
return res.status(500).json({ error: (error as Error).message });
}
} }
} }
}; };
......
...@@ -34,6 +34,17 @@ ...@@ -34,6 +34,17 @@
"nullable": true, "nullable": true,
"example": "Lớp chuyên toán" "example": "Lớp chuyên toán"
}, },
"course_id": {
"type": "string",
"format": "uuid",
"nullable": true,
"example": "7c1a4d9c-3a2b-4c58-9df4-8e2c2d9a3c10"
},
"status": {
"type": "string",
"nullable": true,
"example": "active"
},
"created_at": { "created_at": {
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
...@@ -55,20 +66,43 @@ ...@@ -55,20 +66,43 @@
"format": "uuid", "format": "uuid",
"nullable": true, "nullable": true,
"example": "2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11" "example": "2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11"
},
"course_id": {
"type": "string",
"format": "uuid",
"nullable": true,
"example": "7c1a4d9c-3a2b-4c58-9df4-8e2c2d9a3c10"
},
"status": {
"type": "string",
"nullable": true,
"example": "active"
} }
} }
} }
},
"parameters": {
"filters": {
"name": "filters",
"in": "query",
"schema": {
"type": "string"
}
},
"sort": {
"name": "sort",
"in": "query",
"schema": {
"type": "string",
"enum": [
"asc",
"desc"
]
}
},
"page": {
"name": "page",
"in": "query",
"schema": {
"type": "integer"
}
},
"pageSize": {
"name": "pageSize",
"in": "query",
"schema": {
"type": "integer"
}
}
} }
}, },
"paths": { "paths": {
...@@ -77,8 +111,20 @@ ...@@ -77,8 +111,20 @@
"tags": [ "tags": [
"Classes" "Classes"
], ],
"summary": "Lấy danh sách lớp học", "parameters": [
"description": "Trả về danh sách lớp học.", {
"$ref": "#/components/parameters/filters"
},
{
"$ref": "#/components/parameters/sort"
},
{
"$ref": "#/components/parameters/page"
},
{
"$ref": "#/components/parameters/pageSize"
}
],
"responses": { "responses": {
"200": { "200": {
"description": "Trả về danh sách lớp học thành công", "description": "Trả về danh sách lớp học thành công",
......
...@@ -12,13 +12,7 @@ _autoroutes(app, { ...@@ -12,13 +12,7 @@ _autoroutes(app, {
log: true log: true
}); });
const swaggerOptions = { app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerFile));
swaggerOptions: {
url: '/swagger.json',
},
};
app.use('/swagger', swaggerUi.serve, swaggerUi.setup(swaggerFile, swaggerOptions));
app.listen(port, () => { app.listen(port, () => {
console.log(`Example app listening on port ${port}`) console.log(`Example app listening on port ${port}`)
......
...@@ -50,7 +50,7 @@ export class classes extends Model<classesAttributes, classesCreationAttributes> ...@@ -50,7 +50,7 @@ export class classes extends Model<classesAttributes, classesCreationAttributes>
createCourse!: Sequelize.BelongsToCreateAssociationMixin<courses>; createCourse!: Sequelize.BelongsToCreateAssociationMixin<courses>;
static initModel(sequelize: Sequelize.Sequelize): typeof classes { static initModel(sequelize: Sequelize.Sequelize): typeof classes {
return classes.init({ return sequelize.define('classes', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -86,7 +86,6 @@ export class classes extends Model<classesAttributes, classesCreationAttributes> ...@@ -86,7 +86,6 @@ export class classes extends Model<classesAttributes, classesCreationAttributes>
allowNull: true allowNull: true
} }
}, { }, {
sequelize,
tableName: 'classes', tableName: 'classes',
schema: 'public', schema: 'public',
timestamps: true, timestamps: true,
...@@ -99,6 +98,6 @@ export class classes extends Model<classesAttributes, classesCreationAttributes> ...@@ -99,6 +98,6 @@ export class classes extends Model<classesAttributes, classesCreationAttributes>
] ]
}, },
] ]
}); }) as typeof classes;
} }
} }
...@@ -38,7 +38,7 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes> ...@@ -38,7 +38,7 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes>
countClasses!: Sequelize.HasManyCountAssociationsMixin; countClasses!: Sequelize.HasManyCountAssociationsMixin;
static initModel(sequelize: Sequelize.Sequelize): typeof courses { static initModel(sequelize: Sequelize.Sequelize): typeof courses {
return courses.init({ return sequelize.define('courses', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -62,7 +62,6 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes> ...@@ -62,7 +62,6 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes>
allowNull: true allowNull: true
} }
}, { }, {
sequelize,
tableName: 'courses', tableName: 'courses',
schema: 'public', schema: 'public',
timestamps: true, timestamps: true,
...@@ -75,6 +74,6 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes> ...@@ -75,6 +74,6 @@ export class courses extends Model<coursesAttributes, coursesCreationAttributes>
] ]
}, },
] ]
}); }) as typeof courses;
} }
} }
...@@ -35,7 +35,7 @@ export class enrollments extends Model<enrollmentsAttributes, enrollmentsCreatio ...@@ -35,7 +35,7 @@ export class enrollments extends Model<enrollmentsAttributes, enrollmentsCreatio
createUser!: Sequelize.BelongsToCreateAssociationMixin<users>; createUser!: Sequelize.BelongsToCreateAssociationMixin<users>;
static initModel(sequelize: Sequelize.Sequelize): typeof enrollments { static initModel(sequelize: Sequelize.Sequelize): typeof enrollments {
return enrollments.init({ return sequelize.define('enrollments', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -63,10 +63,9 @@ export class enrollments extends Model<enrollmentsAttributes, enrollmentsCreatio ...@@ -63,10 +63,9 @@ export class enrollments extends Model<enrollmentsAttributes, enrollmentsCreatio
allowNull: true allowNull: true
} }
}, { }, {
sequelize,
tableName: 'enrollments', tableName: 'enrollments',
schema: 'public', schema: 'public',
timestamps: true timestamps: true
}); }) as typeof enrollments;
} }
} }
...@@ -36,7 +36,7 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple ...@@ -36,7 +36,7 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple
countUsers!: Sequelize.HasManyCountAssociationsMixin; countUsers!: Sequelize.HasManyCountAssociationsMixin;
static initModel(sequelize: Sequelize.Sequelize): typeof roles { static initModel(sequelize: Sequelize.Sequelize): typeof roles {
return roles.init({ return sequelize.define('roles', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -56,7 +56,6 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple ...@@ -56,7 +56,6 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple
allowNull: true allowNull: true
} }
}, { }, {
sequelize,
tableName: 'roles', tableName: 'roles',
schema: 'public', schema: 'public',
timestamps: true, timestamps: true,
...@@ -69,6 +68,6 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple ...@@ -69,6 +68,6 @@ export class roles extends Model<rolesAttributes, rolesCreationAttributes> imple
] ]
}, },
] ]
}); }) as typeof roles;
} }
} }
...@@ -27,7 +27,7 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri ...@@ -27,7 +27,7 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri
createUser!: Sequelize.BelongsToCreateAssociationMixin<users>; createUser!: Sequelize.BelongsToCreateAssociationMixin<users>;
static initModel(sequelize: Sequelize.Sequelize): typeof user_auth { static initModel(sequelize: Sequelize.Sequelize): typeof user_auth {
return user_auth.init({ return sequelize.define('user_auth', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -47,7 +47,6 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri ...@@ -47,7 +47,6 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri
allowNull: true allowNull: true
} }
}, { }, {
sequelize,
tableName: 'user_auth', tableName: 'user_auth',
schema: 'public', schema: 'public',
timestamps: true, timestamps: true,
...@@ -60,6 +59,6 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri ...@@ -60,6 +59,6 @@ export class user_auth extends Model<user_authAttributes, user_authCreationAttri
] ]
}, },
] ]
}); }) as typeof user_auth;
} }
} }
...@@ -61,7 +61,7 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple ...@@ -61,7 +61,7 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple
countUser_auths!: Sequelize.HasManyCountAssociationsMixin; countUser_auths!: Sequelize.HasManyCountAssociationsMixin;
static initModel(sequelize: Sequelize.Sequelize): typeof users { static initModel(sequelize: Sequelize.Sequelize): typeof users {
return users.init({ return sequelize.define('users', {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
allowNull: false, allowNull: false,
...@@ -97,7 +97,6 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple ...@@ -97,7 +97,6 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple
} }
} }
}, { }, {
sequelize,
tableName: 'users', tableName: 'users',
schema: 'public', schema: 'public',
timestamps: true, timestamps: true,
...@@ -110,6 +109,6 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple ...@@ -110,6 +109,6 @@ export class users extends Model<usersAttributes, usersCreationAttributes> imple
] ]
}, },
] ]
}); }) as typeof users;
} }
} }
import { models } from '#scripts/database-gen.js'; import { models } from '#scripts/database-gen.js';
import { Op } from 'sequelize';
export class ClassesProvider { export class ClassesProvider {
async getAllClasses() { async getAllClasses(params: { filters?: string, sort?: string, page?: number, pageSize?: number }) {
try { const { filters, sort, page = 1, pageSize = 10 } = params;
const data = await models.classes.findAll({
attributes: ['id', 'name'],
order: [['id', 'DESC']]
});
return data; const offset = (page - 1) * pageSize;
} catch (error) {
console.error("Lỗi khi lấy danh sách classes:", error); const where: any = {};
throw error; if (filters) {
where.name = { [Op.like]: `%${filters}%` };
} }
return await models.classes.findAndCountAll({
where,
order: sort ? [['created_at', sort]] : [['created_at', 'DESC']],
limit: pageSize,
offset: offset
});
} }
async getClassById(classId: number) { async getClassById(classId: number) {
......
...@@ -6,6 +6,12 @@ const sequelize = new Sequelize('challenge_db', 'postgres', '123456', { ...@@ -6,6 +6,12 @@ const sequelize = new Sequelize('challenge_db', 'postgres', '123456', {
port: 2550, port: 2550,
dialect: 'postgres', dialect: 'postgres',
logging: false, logging: false,
define: {
underscored: true,
timestamps: false,
createdAt: 'created_at',
updatedAt: 'updated_at',
},
}); });
const models = initModels(sequelize); const models = initModels(sequelize);
......
...@@ -27,6 +27,17 @@ const classSchemas = { ...@@ -27,6 +27,17 @@ const classSchemas = {
nullable: true, nullable: true,
example: 'Lớp chuyên toán', example: 'Lớp chuyên toán',
}, },
course_id: {
type: 'string',
format: 'uuid',
nullable: true,
example: '7c1a4d9c-3a2b-4c58-9df4-8e2c2d9a3c10',
},
status: {
type: 'string',
nullable: true,
example: 'active',
},
created_at: { created_at: {
type: 'string', type: 'string',
format: 'date-time', format: 'date-time',
...@@ -49,17 +60,6 @@ const classSchemas = { ...@@ -49,17 +60,6 @@ const classSchemas = {
nullable: true, nullable: true,
example: '2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11', example: '2b4f6f8e-19f6-4c5d-93c2-4d7a7c3d1e11',
}, },
course_id: {
type: 'string',
format: 'uuid',
nullable: true,
example: '7c1a4d9c-3a2b-4c58-9df4-8e2c2d9a3c10',
},
status: {
type: 'string',
nullable: true,
example: 'active',
},
}, },
}, },
}; };
......
...@@ -14,6 +14,28 @@ const swaggerOptions: Options = { ...@@ -14,6 +14,28 @@ const swaggerOptions: Options = {
schemas: { schemas: {
...classSchemas, ...classSchemas,
}, },
parameters: {
filters: {
name: 'filters',
in: 'query',
schema: { type: 'string' }
},
sort: {
name: 'sort',
in: 'query',
schema: { type: 'string', enum: ['asc', 'desc'] }
},
page: {
name: 'page',
in: 'query',
schema: { type: 'integer' }
},
pageSize: {
name: 'pageSize',
in: 'query',
schema: { type: 'integer' }
},
}
}, },
}, },
......
...@@ -37,9 +37,15 @@ ...@@ -37,9 +37,15 @@
"#models/*": [ "#models/*": [
"./src/models/*" "./src/models/*"
], ],
"#controllers/*": [
"./src/controllers/*"
],
"#interfaces/*": [ "#interfaces/*": [
"./src/interfaces/*" "./src/interfaces/*"
], ],
"#docs/*": [
"./src/docs/*"
],
"#*": [ "#*": [
"./src/*" "./src/*"
] ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment