From 04dbf410dfe1d0ca491674e8c2951dbeb74a54c5 Mon Sep 17 00:00:00 2001 From: harshithnrao Date: Mon, 10 Mar 2025 21:22:24 +0530 Subject: [PATCH] swagger advancement --- src/app-config/config.local.json | 6 +- src/feedback/feedback.controller.ts | 263 +++++++++++++--- src/feedback/feedback.entity.ts | 16 +- .../question-addl-detail.controller.ts | 271 +++++++++++++++-- .../question-addl-detail.entity.ts | 15 +- src/question-tag/question-tag.controller.ts | 268 +++++++++++++++-- src/question-tag/question-tag.entity.ts | 14 +- src/question/question.controller.ts | 282 +++++++++++++++--- src/question/question.entity.ts | 15 +- src/ranking/ranking.controller.ts | 268 +++++++++++++++-- src/ranking/ranking.entity.ts | 16 +- src/results/results.controller.ts | 270 +++++++++++++++-- src/results/results.entity.ts | 17 +- .../test-addl-detail.controller.ts | 270 +++++++++++++++-- .../test-addl-detail.entity.ts | 15 +- src/test-assign/test-assign.controller.ts | 270 +++++++++++++++-- src/test-assign/test-assign.entity.ts | 17 +- src/test-detail/test-detail.controller.ts | 270 +++++++++++++++-- src/test-detail/test-detail.entity.ts | 16 +- src/test/test.controller.ts | 268 +++++++++++++++-- src/test/test.entity.ts | 16 +- 21 files changed, 2521 insertions(+), 342 deletions(-) diff --git a/src/app-config/config.local.json b/src/app-config/config.local.json index 82b9971..edf9962 100644 --- a/src/app-config/config.local.json +++ b/src/app-config/config.local.json @@ -35,10 +35,10 @@ }, "swaggerConfig": { "swagger": { - "title": "Remedify Content API", - "description": "Remedify Content API", + "title": "Remedify Assessment API", + "description": "Remedify Assessment API", "version": "1.0.0", - "tag": "Remedify Content API" + "tag": "Remedify assessment API" } } } diff --git a/src/feedback/feedback.controller.ts b/src/feedback/feedback.controller.ts index cf4148c..4c81877 100644 --- a/src/feedback/feedback.controller.ts +++ b/src/feedback/feedback.controller.ts @@ -2,105 +2,300 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { FeedbackService } from './feedback.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import Feedback from './feedback.entity'; +import Feedback from './feedback.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('feedback') @Controller('feedback') export class FeedbackController { constructor(private feedbackService: FeedbackService) {} @Get("/all") + @ApiOperation({ summary: 'Get all feedbacks' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all feedbacks', + }) + @ApiResponse({ + status: 404, + description: 'No feedback found', + }) async getAllFeedbacks(@Res() res: Response) { const response = await this.feedbackService.findAll() || []; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get a feedback by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the feedback' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Feedback not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Feedback not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved feedback', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + const response = await this.feedbackService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Feedback with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter feedbacks based on criteria' }) + @ApiBody({ type: Feedback, description: 'Criteria to filter feedbacks' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No feedbacks found matching the filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No feedback found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered feedbacks', + }) async filter(@Body() feedback: Feedback, @Res() res: Response) { - if(!feedback) { + if (!feedback) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + const response = await this.feedbackService.filter(feedback) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No feedback found matching the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Create a new feedback' }) + @ApiBody({ type: Feedback, description: 'Feedback data to create' }) + @ApiResponse({ + status: 400, + description: 'Invalid feedback data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created feedback', + }) async insert(@Body() feedback: Feedback, @Res() res: Response) { - if(!feedback) { + if (!feedback) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + delete feedback.id; - const response = await this.feedbackService.upsert(feedback, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing feedback' }) + @ApiBody({ type: Feedback, description: 'Feedback data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid data or missing ID', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Feedback not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Feedback not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated feedback', + }) async update(@Body() feedback: Feedback, @Res() res: Response) { - if(!feedback || !feedback.id) { + if (!feedback || !feedback.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - + const response = await this.feedbackService.upsert(feedback, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Feedback with ID ${feedback.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a feedback by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the feedback to delete' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Feedback not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Feedback not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted feedback', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.feedbackService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); - } + const response = await this.feedbackService.remove(id) || {}; + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Feedback with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); + } } diff --git a/src/feedback/feedback.entity.ts b/src/feedback/feedback.entity.ts index c0db6b5..5be2c0a 100644 --- a/src/feedback/feedback.entity.ts +++ b/src/feedback/feedback.entity.ts @@ -1,46 +1,60 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'feedback' , paranoid : true}) +@Table({ tableName: 'feedback', paranoid: true }) export default class Feedback extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) userId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) feedbackText: string; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) rating: number; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/question-addl-detail/question-addl-detail.controller.ts b/src/question-addl-detail/question-addl-detail.controller.ts index e696481..6c3a099 100644 --- a/src/question-addl-detail/question-addl-detail.controller.ts +++ b/src/question-addl-detail/question-addl-detail.controller.ts @@ -2,105 +2,310 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { QuestionAddlDetailService } from './question-addl-detail.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import QuestionAddlDetail from './question-addl-detail.entity'; +import QuestionAddlDetail from './question-addl-detail.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('question-addl-detail') @Controller('questionAddlDetail') export class QuestionAddlDetailController { - constructor(private questionAddlDetailService: QuestionAddlDetailService) {} + constructor(private questionAddlDetailService: QuestionAddlDetailService) { } @Get("/all") + @ApiOperation({ summary: 'Get all additional question details' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all question details', + }) + @ApiResponse({ + status: 404, + description: 'No question details found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No question details found" + }, + "data": null + } + }) async getAllQuestionAddlDetails(@Res() res: Response) { const response = await this.questionAddlDetailService.findAll() || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const httpResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'Question details not found' + }, null); + res.status(404).send(httpResponse); + return; + } + const httpResponse = new GenericResponse(null, response); res.send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get a question detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question detail' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved question detail', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionAddlDetailService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter question details based on criteria' }) + @ApiBody({ type: QuestionAddlDetail, description: 'Criteria to filter question details' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No question details found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No question details found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered question details', + }) async filter(@Body() questionAddlDetail: QuestionAddlDetail, @Res() res: Response) { - if(!questionAddlDetail) { + if (!questionAddlDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionAddlDetailService.filter(questionAddlDetail) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No question details found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Create a new question detail' }) + @ApiBody({ type: QuestionAddlDetail, description: 'Question detail data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid question detail data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created question detail', + }) async insert(@Body() questionAddlDetail: QuestionAddlDetail, @Res() res: Response) { - if(!questionAddlDetail) { + if (!questionAddlDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete questionAddlDetail.id; - const response = await this.questionAddlDetailService.upsert(questionAddlDetail, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing question detail' }) + @ApiBody({ type: QuestionAddlDetail, description: 'Question detail data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid data or missing ID', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated question detail', + }) async update(@Body() questionAddlDetail: QuestionAddlDetail, @Res() res: Response) { - if(!questionAddlDetail || !questionAddlDetail.id) { + if (!questionAddlDetail || !questionAddlDetail.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.questionAddlDetailService.upsert(questionAddlDetail, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question detail with ID ${questionAddlDetail.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a question detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question detail to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted question detail', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionAddlDetailService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/question-addl-detail/question-addl-detail.entity.ts b/src/question-addl-detail/question-addl-detail.entity.ts index 7fe401c..9ca086b 100644 --- a/src/question-addl-detail/question-addl-detail.entity.ts +++ b/src/question-addl-detail/question-addl-detail.entity.ts @@ -1,43 +1,56 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'question_additional_details' , paranoid : true}) +@Table({ tableName: 'question_additional_details', paranoid: true }) export default class QuestionAddlDetail extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) questionId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) addlDataType: string; + @ApiProperty({ type: String }) @Column(DataType.TEXT) addlDataName: string; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/question-tag/question-tag.controller.ts b/src/question-tag/question-tag.controller.ts index 3129335..45d2913 100644 --- a/src/question-tag/question-tag.controller.ts +++ b/src/question-tag/question-tag.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { QuestionTagService } from './question-tag.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import QuestionTag from './question-tag.entity'; +import QuestionTag from './question-tag.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('question-tag') @Controller('question-tag') export class QuestionTagController { constructor(private questionTagService: QuestionTagService) {} @Get("/all") + @ApiOperation({ summary: 'Get all question tags' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all question tags', + }) + @ApiResponse({ + status: 404, + description: 'No question tags found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No question tags found" + }, + "data": null + } + }) async getAllQuestionTags(@Res() res: Response) { const response = await this.questionTagService.findAll() || []; - const httpResponse = new GenericResponse(null, response) + if(!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No question tags found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get a question tag by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question tag' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question tag not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question tag not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved question tag', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionTagService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question tag with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter question tags based on criteria' }) + @ApiBody({ type: QuestionTag, description: 'Criteria to filter question tags' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No question tags found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No question tags found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered question tags', + }) async filter(@Body() questionTag: QuestionTag, @Res() res: Response) { - if(!questionTag) { + if (!questionTag) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionTagService.filter(questionTag) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No question tags found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Create a new question tag' }) + @ApiBody({ type: QuestionTag, description: 'Question tag data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid question tag data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created question tag', + }) async insert(@Body() questionTag: QuestionTag, @Res() res: Response) { - if(!questionTag) { + if (!questionTag) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete questionTag.id; - const response = await this.questionTagService.upsert(questionTag, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing question tag' }) + @ApiBody({ type: QuestionTag, description: 'Question tag data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid data or missing ID', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question tag not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question tag not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated question tag', + }) async update(@Body() questionTag: QuestionTag, @Res() res: Response) { - if(!questionTag || !questionTag.id) { + if (!questionTag || !questionTag.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.questionTagService.upsert(questionTag, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question tag with ID ${questionTag.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a question tag by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question tag to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question tag not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question tag not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted question tag', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.questionTagService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question tag with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/question-tag/question-tag.entity.ts b/src/question-tag/question-tag.entity.ts index c25ff7c..bed26ab 100644 --- a/src/question-tag/question-tag.entity.ts +++ b/src/question-tag/question-tag.entity.ts @@ -1,40 +1,52 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'question_tag' , paranoid : true}) +@Table({ tableName: 'question_tag', paranoid: true }) export default class QuestionTag extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) questionId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) tagName: string; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/question/question.controller.ts b/src/question/question.controller.ts index afbe9a6..2f632d9 100644 --- a/src/question/question.controller.ts +++ b/src/question/question.controller.ts @@ -2,105 +2,319 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { QuestionService } from './question.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import Question from './question.entity'; +import Question from './question.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('question') @Controller('question') export class QuestionController { constructor(private questionService: QuestionService) {} @Get("/all") + @ApiOperation({ summary: 'Get all questions' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all questions', + }) + @ApiResponse({ + status: 404, + description: 'No questions found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Questions not found" + }, + "data": null + } + }) async getAllQuestions(@Res() res: Response) { const response = await this.questionService.findAll() || []; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const httpResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'Questions not found' + }, null); + res.status(404).send(httpResponse); + return; + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get a question by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved question', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + const response = await this.questionService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter questions based on criteria' }) + @ApiBody({ type: Question, description: 'Criteria to filter questions' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No questions found matching the filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No questions found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered questions', + }) async filter(@Body() question: Question, @Res() res: Response) { - if(!question) { + if (!question) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + const response = await this.questionService.filter(question) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No questions found matching the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Create a new question' }) + @ApiBody({ type: Question, description: 'Question data to create' }) + @ApiResponse({ + status: 400, + description: 'Invalid question data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created question', + }) async insert(@Body() question: Question, @Res() res: Response) { - if(!question) { + if (!question) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } + delete question.id; - const response = await this.questionService.upsert(question, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing question' }) + @ApiBody({ type: Question, description: 'Question data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid data or missing ID', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated question', + }) async update(@Body() question: Question, @Res() res: Response) { - if(!question || !question.id) { + if (!question || !question.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - + const response = await this.questionService.upsert(question, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question with ID ${question.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a question by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'ID of the question to delete' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Question not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Question not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted question', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.questionService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); - } + const response = await this.questionService.remove(id) || {}; + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Question with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); + } } diff --git a/src/question/question.entity.ts b/src/question/question.entity.ts index 233e6bc..9c31a65 100644 --- a/src/question/question.entity.ts +++ b/src/question/question.entity.ts @@ -1,43 +1,56 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'question' , paranoid : true}) +@Table({ tableName: 'question', paranoid: true }) export default class Question extends Model { + @ApiProperty({ type: String }) @Column(DataType.TEXT) content: string; + @ApiProperty({ type: String }) @Column(DataType.TEXT) questionType: string; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) hardness: number; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/ranking/ranking.controller.ts b/src/ranking/ranking.controller.ts index f32bdfe..8d45280 100644 --- a/src/ranking/ranking.controller.ts +++ b/src/ranking/ranking.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { RankingService } from './ranking.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import Ranking from './ranking.entity'; +import Ranking from './ranking.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('ranking') @Controller('ranking') export class RankingController { constructor(private rankingService: RankingService) {} @Get("/all") + @ApiOperation({ summary: 'Get all rankings' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all rankings', + }) + @ApiResponse({ + status: 404, + description: 'No rankings found', + example:{ + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No rankings found" + }, + "data": null + } + }) async getAllRankings(@Res() res: Response) { const response = await this.rankingService.findAll() || []; - const httpResponse = new GenericResponse(null, response) + if(!response){ + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No rankings found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get ranking by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Ranking ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Ranking not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Ranking not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved ranking by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.rankingService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Ranking with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter rankings based on criteria' }) + @ApiBody({ type: Ranking, description: 'Filter criteria for rankings' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No rankings found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No rankings found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered rankings', + }) async filter(@Body() ranking: Ranking, @Res() res: Response) { - if(!ranking) { + if (!ranking) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.rankingService.filter(ranking) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No rankings found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new ranking' }) + @ApiBody({ type: Ranking, description: 'Ranking data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid ranking data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created a ranking', + }) async insert(@Body() ranking: Ranking, @Res() res: Response) { - if(!ranking) { + if (!ranking) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete ranking.id; - const response = await this.rankingService.upsert(ranking, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing ranking' }) + @ApiBody({ type: Ranking, description: 'Ranking data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid ranking data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Ranking not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Ranking not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated ranking', + }) async update(@Body() ranking: Ranking, @Res() res: Response) { - if(!ranking || !ranking.id) { + if (!ranking || !ranking.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.rankingService.upsert(ranking, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Ranking with ID ${ranking.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a ranking by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Ranking ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Ranking not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Ranking not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted ranking', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.rankingService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Ranking with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/ranking/ranking.entity.ts b/src/ranking/ranking.entity.ts index 0622ab4..1ccabad 100644 --- a/src/ranking/ranking.entity.ts +++ b/src/ranking/ranking.entity.ts @@ -1,46 +1,60 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'ranking' , paranoid : true}) +@Table({ tableName: 'ranking', paranoid: true }) export default class Ranking extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) bookId: number; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) userId: number; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) rank: number; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/results/results.controller.ts b/src/results/results.controller.ts index 25e440c..52a4b0d 100644 --- a/src/results/results.controller.ts +++ b/src/results/results.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { ResultsService } from './results.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import Results from './results.entity'; +import Results from './results.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('results') @Controller('results') export class ResultsController { constructor(private resultsService: ResultsService) {} @Get("/all") - async getAllResultss(@Res() res: Response) { + @ApiOperation({ summary: 'Get all results' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all results', + }) + @ApiResponse({ + status: 404, + description: 'No results found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No results found" + }, + "data": null + } + }) + async getAllResults(@Res() res: Response) { const response = await this.resultsService.findAll() || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No results found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get result by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Result ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Result not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Result not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved result by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.resultsService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Result with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter results based on criteria' }) + @ApiBody({ type: Results, description: 'Filter criteria for results' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No results found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No results found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered results', + }) async filter(@Body() results: Results, @Res() res: Response) { - if(!results) { + if (!results) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.resultsService.filter(results) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No results found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new result' }) + @ApiBody({ type: Results, description: 'Result data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid result data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created a result', + }) async insert(@Body() results: Results, @Res() res: Response) { - if(!results) { + if (!results) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete results.id; - const response = await this.resultsService.upsert(results, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing result' }) + @ApiBody({ type: Results, description: 'Result data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid result data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Result not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Result not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated result', + }) async update(@Body() results: Results, @Res() res: Response) { - if(!results || !results.id) { + if (!results || !results.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.resultsService.upsert(results, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Result with ID ${results.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a result by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Result ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Result not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Result not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted result', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.resultsService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Result with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/results/results.entity.ts b/src/results/results.entity.ts index 47d2290..549cc69 100644 --- a/src/results/results.entity.ts +++ b/src/results/results.entity.ts @@ -1,49 +1,64 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'results' , paranoid : true}) +@Table({ tableName: 'results', paranoid: true }) export default class Results extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) userId: number; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) score: number; + @ApiProperty({ type: Boolean }) @Column(DataType.BOOLEAN) passing: boolean; + @ApiProperty({ type: String }) @Column(DataType.TEXT) description: string; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/test-addl-detail/test-addl-detail.controller.ts b/src/test-addl-detail/test-addl-detail.controller.ts index 2ec94d4..152600a 100644 --- a/src/test-addl-detail/test-addl-detail.controller.ts +++ b/src/test-addl-detail/test-addl-detail.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { TestAddlDetailService } from './test-addl-detail.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import TestAddlDetail from './test-addl-detail.entity'; +import TestAddlDetail from './test-addl-detail.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('test-addl-detail') @Controller('testAddlDetail') export class TestAddlDetailController { constructor(private testAddlDetailService: TestAddlDetailService) {} @Get("/all") + @ApiOperation({ summary: 'Get all additional test details' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all additional test details', + }) + @ApiResponse({ + status: 404, + description: 'No additional test details found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test details found" + }, + "data": null + } + }) async getAllTestAddlDetails(@Res() res: Response) { const response = await this.testAddlDetailService.findAll() || []; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test details found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get additional test detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Additional Detail ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test additional detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test additional detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved test additional detail by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAddlDetailService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test additional detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter additional test details based on criteria' }) + @ApiBody({ type: TestAddlDetail, description: 'Filter criteria for additional test details' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No additional test details found based on the filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test details found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered additional test details', + }) async filter(@Body() testAddlDetail: TestAddlDetail, @Res() res: Response) { - if(!testAddlDetail) { + if (!testAddlDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAddlDetailService.filter(testAddlDetail) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test details found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new additional test detail' }) + @ApiBody({ type: TestAddlDetail, description: 'Additional test detail data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid test detail data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created additional test detail', + }) async insert(@Body() testAddlDetail: TestAddlDetail, @Res() res: Response) { - if(!testAddlDetail) { + if (!testAddlDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete testAddlDetail.id; - const response = await this.testAddlDetailService.upsert(testAddlDetail, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing additional test detail' }) + @ApiBody({ type: TestAddlDetail, description: 'Additional test detail data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid test detail data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test detail successfully updated', + }) async update(@Body() testAddlDetail: TestAddlDetail, @Res() res: Response) { - if(!testAddlDetail || !testAddlDetail.id) { + if (!testAddlDetail || !testAddlDetail.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.testAddlDetailService.upsert(testAddlDetail, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test detail with ID ${testAddlDetail.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete an additional test detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Additional Detail ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test additional detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test additional detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test additional detail successfully deleted', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAddlDetailService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test additional detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/test-addl-detail/test-addl-detail.entity.ts b/src/test-addl-detail/test-addl-detail.entity.ts index 88d7355..0736244 100644 --- a/src/test-addl-detail/test-addl-detail.entity.ts +++ b/src/test-addl-detail/test-addl-detail.entity.ts @@ -1,43 +1,56 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'test_additional_details' , paranoid : true}) +@Table({ tableName: 'test_additional_details', paranoid: true }) export default class TestAddlDetail extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) addlDataType: string; + @ApiProperty({ type: String }) @Column(DataType.TEXT) addlDataName: string; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/test-assign/test-assign.controller.ts b/src/test-assign/test-assign.controller.ts index 3e8ee55..66112a7 100644 --- a/src/test-assign/test-assign.controller.ts +++ b/src/test-assign/test-assign.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { TestAssignService } from './test-assign.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import TestAssign from './test-assign.entity'; +import TestAssign from './test-assign.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('test-assign') @Controller('testAssign') export class TestAssignController { constructor(private testAssignService: TestAssignService) {} @Get("/all") + @ApiOperation({ summary: 'Get all test assignments' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all test assignments', + }) + @ApiResponse({ + status: 404, + description: 'No test assignments found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test assignments found" + }, + "data": null + } + }) async getAllTestAssigns(@Res() res: Response) { const response = await this.testAssignService.findAll() || []; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test assignments found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get test assignment by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Assignment ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test assignment not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test assignment not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved test assignment by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAssignService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test assignment with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter test assignments based on criteria' }) + @ApiBody({ type: TestAssign, description: 'Filter criteria for test assignments' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No test assignments found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test assignments found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered test assignments', + }) async filter(@Body() testAssign: TestAssign, @Res() res: Response) { - if(!testAssign) { + if (!testAssign) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAssignService.filter(testAssign) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test assignments found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new test assignment' }) + @ApiBody({ type: TestAssign, description: 'Test assignment data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid test assignment data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Test assignment successfully created', + }) async insert(@Body() testAssign: TestAssign, @Res() res: Response) { - if(!testAssign) { + if (!testAssign) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete testAssign.id; - const response = await this.testAssignService.upsert(testAssign, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing test assignment' }) + @ApiBody({ type: TestAssign, description: 'Test assignment data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid test assignment data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test assignment not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test assignment not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test assignment successfully updated', + }) async update(@Body() testAssign: TestAssign, @Res() res: Response) { - if(!testAssign || !testAssign.id) { + if (!testAssign || !testAssign.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.testAssignService.upsert(testAssign, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test assignment with ID ${testAssign.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a test assignment by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Assignment ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test assignment not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test assignment not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test assignment successfully deleted', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testAssignService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test assignment with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/test-assign/test-assign.entity.ts b/src/test-assign/test-assign.entity.ts index 5a29de6..cc5f956 100644 --- a/src/test-assign/test-assign.entity.ts +++ b/src/test-assign/test-assign.entity.ts @@ -1,49 +1,64 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'test_assign' , paranoid : true}) +@Table({ tableName: 'test_assign', paranoid: true }) export default class TestAssign extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) userId: number; + @ApiProperty({ type: Date, format: 'date-time' }) @Column(DataType.DATEONLY) assignedAt: Date; + @ApiProperty({ type: Date, format: 'date-time' }) @Column(DataType.DATEONLY) startTime: Date; + @ApiProperty({ type: Date, format: 'date-time' }) @Column(DataType.DATEONLY) endTime: Date; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/test-detail/test-detail.controller.ts b/src/test-detail/test-detail.controller.ts index a1c8a15..318f513 100644 --- a/src/test-detail/test-detail.controller.ts +++ b/src/test-detail/test-detail.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { TestDetailService } from './test-detail.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import TestDetail from './test-detail.entity'; +import TestDetail from './test-detail.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('test-detail') @Controller('testDetail') export class TestDetailController { constructor(private testDetailService: TestDetailService) {} @Get("/all") + @ApiOperation({ summary: 'Get all test details' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all test details', + }) + @ApiResponse({ + status: 404, + description: 'No test details found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test details found" + }, + "data": null + } + }) async getAllTestDetails(@Res() res: Response) { const response = await this.testDetailService.findAll() || []; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test details found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get test detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Detail ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved test detail by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testDetailService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter test details based on criteria' }) + @ApiBody({ type: TestDetail, description: 'Filter criteria for test details' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No test details found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No test details found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered test details', + }) async filter(@Body() testDetail: TestDetail, @Res() res: Response) { - if(!testDetail) { + if (!testDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testDetailService.filter(testDetail) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No test details found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new test detail' }) + @ApiBody({ type: TestDetail, description: 'Test detail data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid test detail data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Test detail successfully created', + }) async insert(@Body() testDetail: TestDetail, @Res() res: Response) { - if(!testDetail) { + if (!testDetail) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete testDetail.id; - const response = await this.testDetailService.upsert(testDetail, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing test detail' }) + @ApiBody({ type: TestDetail, description: 'Test detail data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid test detail data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test detail successfully updated', + }) async update(@Body() testDetail: TestDetail, @Res() res: Response) { - if(!testDetail || !testDetail.id) { + if (!testDetail || !testDetail.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.testDetailService.upsert(testDetail, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test detail with ID ${testDetail.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a test detail by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test Detail ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test detail not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test detail not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Test detail successfully deleted', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testDetailService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test detail with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/test-detail/test-detail.entity.ts b/src/test-detail/test-detail.entity.ts index ba96bd9..4cdff1c 100644 --- a/src/test-detail/test-detail.entity.ts +++ b/src/test-detail/test-detail.entity.ts @@ -1,46 +1,60 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'test_detail' , paranoid : true}) +@Table({ tableName: 'test_detail', paranoid: true }) export default class TestDetail extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) testId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) questionType: string; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) hardness: number; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) count: number; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; } diff --git a/src/test/test.controller.ts b/src/test/test.controller.ts index fae0e94..2291718 100644 --- a/src/test/test.controller.ts +++ b/src/test/test.controller.ts @@ -2,105 +2,309 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/co import { TestService } from './test.service'; import { Response } from 'express'; import { GenericResponse } from '../common/GenericResponse.model'; -import Test from './test.entity'; +import Test from './test.entity'; +import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger'; +@ApiTags('test') @Controller('test') export class TestController { constructor(private testService: TestService) {} @Get("/all") + @ApiOperation({ summary: 'Get all tests' }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved all tests', + }) + @ApiResponse({ + status: 404, + description: 'No tests found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No tests found" + }, + "data": null + } + }) async getAllTests(@Res() res: Response) { const response = await this.testService.findAll() || []; - const httpResponse = new GenericResponse(null, response) + if(!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No tests found' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.send(httpResponse); } @Get(':id') + @ApiOperation({ summary: 'Get test by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test ID' }) + @ApiResponse({ + status: 400, + description: 'ID is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully retrieved test by ID', + }) async findById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testService.findByPk(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Post('/filter') + @ApiOperation({ summary: 'Filter tests based on criteria' }) + @ApiBody({ type: Test, description: 'Filter criteria for tests' }) + @ApiResponse({ + status: 400, + description: 'Invalid filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_CRITERIA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'No tests found based on filter criteria', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "No tests found based on the filter criteria" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully filtered tests', + }) async filter(@Body() test: Test, @Res() res: Response) { - if(!test) { + if (!test) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_CRITERIA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testService.filter(test) || []; - const httpResponse = new GenericResponse(null, response) + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: 'No tests found based on the filter criteria' + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); res.status(200).send(httpResponse); } - + @Post() + @ApiOperation({ summary: 'Insert a new test' }) + @ApiBody({ type: Test, description: 'Test data to insert' }) + @ApiResponse({ + status: 400, + description: 'Invalid test data', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 201, + description: 'Successfully created a test', + }) async insert(@Body() test: Test, @Res() res: Response) { - if(!test) { + if (!test) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', - exceptionMessage: 'ERR.NO_ID_REQ', + exceptionMessage: 'ERR.INVALID_DATA', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } delete test.id; - const response = await this.testService.upsert(test, true); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + const httpResponse = new GenericResponse(null, response); + res.status(201).send(httpResponse); } @Put() + @ApiOperation({ summary: 'Update an existing test' }) + @ApiBody({ type: Test, description: 'Test data to update' }) + @ApiResponse({ + status: 400, + description: 'Invalid test data or ID missing', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.INVALID_DATA", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully updated test', + }) async update(@Body() test: Test, @Res() res: Response) { - if(!test || !test.id) { + if (!test || !test.id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } - const response = await this.testService.upsert(test, false); - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test with ID ${test.id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } @Delete(':id') + @ApiOperation({ summary: 'Delete a test by ID' }) + @ApiParam({ name: 'id', type: Number, description: 'Test ID to delete' }) + @ApiResponse({ + status: 400, + description: 'ID parameter is required', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NO_ID_REQ", + "stackTrace": "Request" + }, + "data": null + } + }) + @ApiResponse({ + status: 404, + description: 'Test not found', + example: { + "notification": { + "exception": true, + "exceptionSeverity": "HIGH", + "exceptionMessage": "ERR.NOT_FOUND", + "stackTrace": "Test not found" + }, + "data": null + } + }) + @ApiResponse({ + status: 200, + description: 'Successfully deleted test', + }) async deleteById(@Param('id') id: number, @Res() res: Response) { - if(!id) { + if (!id) { const response = new GenericResponse({ exception: true, exceptionSeverity: 'HIGH', exceptionMessage: 'ERR.NO_ID_REQ', stackTrace: 'Request' }, null); - res.send(response); - return; + return res.status(400).send(response); } const response = await this.testService.remove(id) || {}; - const httpResponse = new GenericResponse(null, response) - res.send(httpResponse); + if (!response) { + const errorResponse = new GenericResponse({ + exception: true, + exceptionSeverity: 'HIGH', + exceptionMessage: 'ERR.NOT_FOUND', + stackTrace: `Test with ID ${id} not found` + }, null); + return res.status(404).send(errorResponse); + } + const httpResponse = new GenericResponse(null, response); + res.status(200).send(httpResponse); } - } diff --git a/src/test/test.entity.ts b/src/test/test.entity.ts index a1e855b..f5dbc1f 100644 --- a/src/test/test.entity.ts +++ b/src/test/test.entity.ts @@ -1,46 +1,60 @@ import { Table, Column, Model, Default, DataType } from 'sequelize-typescript'; +import { ApiProperty } from '@nestjs/swagger'; -@Table({ tableName: 'test' , paranoid : true}) +@Table({ tableName: 'test', paranoid: true }) export default class Test extends Model { + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) userId: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) title: string; + @ApiProperty({ type: String }) @Column(DataType.TEXT) description: string; + @ApiProperty({ type: Number }) @Column(DataType.BIGINT) textbookId: number; + @ApiProperty({ type: Date, default: new Date() }) @Default(new Date()) @Column(DataType.DATEONLY) validFrom: Date; + @ApiProperty({ type: Date, default: new Date("2070-12-31") }) @Default(new Date("2070-12-31")) @Column(DataType.DATEONLY) validTill: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) createdAt: Date; + @ApiProperty({ type: String, format: 'date-time' }) @Column(DataType.DATEONLY) updatedAt: Date; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) createdBy: string; + @ApiProperty({ type: String, required: false }) @Column(DataType.TEXT) modifiedBy: string; + @ApiProperty({ type: Date, required: false }) @Column(DataType.DATEONLY) deletedAt: Date; + @ApiProperty({ type: Number }) @Column(DataType.NUMBER) version: number; + @ApiProperty({ type: String }) @Column(DataType.TEXT) status: string; }