minor bug fixes and validation dtos

This commit is contained in:
harshithnrao 2025-04-06 17:55:09 +05:30
parent dab3b9dc61
commit 75673ae96d
33 changed files with 1402 additions and 104 deletions

108
package-lock.json generated
View File

@ -15,15 +15,18 @@
"@nestjs/core": "^10.4.15",
"@nestjs/jwt": "^11.0.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-express": "^10.4.15",
"@nestjs/platform-socket.io": "^10.4.15",
"@nestjs/swagger": "^8.1.1",
"@nestjs/typeorm": "^10.0.1",
"@nestjs/websockets": "^10.4.15",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.3.1",
"handlebars": "^4.7.8",
"ioredis": "^5.6.0",
"moment": "^2.30.1",
"multer": "^1.4.5-lts.2",
"nodemailer": "^6.9.9",
"otp-generator": "^4.0.1",
"passport": "^0.7.0",
@ -1918,6 +1921,24 @@
"@nestjs/core": "^10.0.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/@nestjs/platform-socket.io": {
"version": "10.4.15",
"resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.15.tgz",
@ -2567,9 +2588,10 @@
}
},
"node_modules/@types/validator": {
"version": "13.11.7",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.7.tgz",
"integrity": "sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q=="
"version": "13.12.3",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.3.tgz",
"integrity": "sha512-2ipwZ2NydGQJImne+FhNdhgRM37e9lCev99KnqkbFHd94Xn/mErARWI1RSLem1QA19ch5kOhzIZd7e8CA2FI8g==",
"license": "MIT"
},
"node_modules/@types/yargs": {
"version": "17.0.32",
@ -3806,6 +3828,23 @@
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
"dev": true
},
"node_modules/class-transformer": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==",
"license": "MIT"
},
"node_modules/class-validator": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
"integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"license": "MIT",
"dependencies": {
"@types/validator": "^13.11.8",
"libphonenumber-js": "^1.10.53",
"validator": "^13.9.0"
}
},
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@ -7050,6 +7089,12 @@
"node": ">= 0.8.0"
}
},
"node_modules/libphonenumber-js": {
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
"integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw==",
"license": "MIT"
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -7409,9 +7454,10 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"version": "1.4.5-lts.2",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz",
"integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==",
"license": "MIT",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
@ -12086,6 +12132,22 @@
"express": "4.21.2",
"multer": "1.4.4-lts.1",
"tslib": "2.8.1"
},
"dependencies": {
"multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
}
}
}
},
"@nestjs/platform-socket.io": {
@ -12626,9 +12688,9 @@
}
},
"@types/validator": {
"version": "13.11.7",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.7.tgz",
"integrity": "sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q=="
"version": "13.12.3",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.3.tgz",
"integrity": "sha512-2ipwZ2NydGQJImne+FhNdhgRM37e9lCev99KnqkbFHd94Xn/mErARWI1RSLem1QA19ch5kOhzIZd7e8CA2FI8g=="
},
"@types/yargs": {
"version": "17.0.32",
@ -13485,6 +13547,21 @@
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
"dev": true
},
"class-transformer": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz",
"integrity": "sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw=="
},
"class-validator": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz",
"integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==",
"requires": {
"@types/validator": "^13.11.8",
"libphonenumber-js": "^1.10.53",
"validator": "^13.9.0"
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@ -15848,6 +15925,11 @@
"type-check": "~0.4.0"
}
},
"libphonenumber-js": {
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
"integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw=="
},
"lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@ -16110,9 +16192,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"version": "1.4.5-lts.2",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz",
"integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",

View File

@ -29,15 +29,18 @@
"@nestjs/core": "^10.4.15",
"@nestjs/jwt": "^11.0.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/platform-express": "^10.4.15",
"@nestjs/platform-socket.io": "^10.4.15",
"@nestjs/swagger": "^8.1.1",
"@nestjs/typeorm": "^10.0.1",
"@nestjs/websockets": "^10.4.15",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.3.1",
"handlebars": "^4.7.8",
"ioredis": "^5.6.0",
"moment": "^2.30.1",
"multer": "^1.4.5-lts.2",
"nodemailer": "^6.9.9",
"otp-generator": "^4.0.1",
"passport": "^0.7.0",

View File

@ -53,19 +53,22 @@
},
"vapidConfig": {
"email": "mailto:example@domain.com",
"publicKey": "BPcIQx6jQlD0m2WA5qzXnHtKtsBhvIf_aRf6foXx3ESiw2Tks6b8tVzzX3hHwerGtWy4togFEiJtk5X-Sq36uVQ",
"privateKey": "v-pRrypniFnPn6UOyDNIKatxoHCI6aqsXCM86L7aTfY"
"publicKey": "BJnRhhooOB7unX8yfpHXgbUVqR03A7zsAppguA7JfHMNmhgZ1-RqbA-y70neaPrtbfO8Q1GsipYIM05_SpLDUP0",
"privateKey": "7OAq3PXC3VCNPus6Mua9rxSO66Vd0j5J5Mv8g7hMbYc"
},
"redisConfig":{
"host":"localhost",
"port":6379,
"db":0
"redisConfig": {
"host": "localhost",
"port": 6379,
"db": 0
},
"googleOauthConfig": {
"clientId":"361418022886-4d4p2v7n9tq8t4tq8t4tq8tq8tq8tq8t.apps.googleusercontent.com",
"clientSecret":"GOCSPX-2Vt7b5Oo4t4t4t4t4t4t4t4t4t4",
"callbackURL":"http://localhost:3000/auth/google-redirect",
"scope":["email","profile"]
"clientId": "361418022886-q8inm4gh7aqhopitpsl87m0vcgces320.apps.googleusercontent.com",
"clientSecret": "GOCSPX-TwyERXKjx-8_U1X68ayJpCssfY",
"callbackURL": "http://localhost:3000/auth/google-redirect",
"scope": [
"email",
"profile"
]
}
}
}

View File

@ -53,19 +53,22 @@
},
"vapidConfig": {
"email": "mailto:example@domain.com",
"publicKey": "BPcIQx6jQlD0m2WA5qzXnHtKtsBhvIf_aRf6foXx3ESiw2Tks6b8tVzzX3hHwerGtWy4togFEiJtk5X-Sq36uVQ",
"privateKey": "v-pRrypniFnPn6UOyDNIKatxoHCI6aqsXCM86L7aTfY"
"publicKey": "BJnRhhooOB7unX8yfpHXgbUVqR03A7zsAppguA7JfHMNmhgZ1-RqbA-y70neaPrtbfO8Q1GsipYIM05_SpLDUP0",
"privateKey": "7OAq3PXC3VCNPus6Mua9rxSO66Vd0j5J5Mv8g7hMbYc"
},
"redisConfig":{
"host":"localhost",
"port":6379,
"db":0
"redisConfig": {
"host": "localhost",
"port": 6379,
"db": 0
},
"googleOauthConfig": {
"clientId":"361418022886-4d4p2v7n9tq8t4tq8t4tq8tq8tq8tq8t.apps.googleusercontent.com",
"clientSecret":"GOCSPX-2Vt7b5Oo4t4t4t4t4t4t4t4t4t4",
"callbackURL":"http://localhost:3000/auth/google-redirect",
"scope":["email","profile"]
"clientId": "361418022886-q8inm4gh7aqhopitpsl87m0vcgces320.apps.googleusercontent.com",
"clientSecret": "GOCSPX-TwyERXKjx-8_U1X68ayJpCssfY",
"callbackURL": "http://localhost:3000/auth/google-redirect",
"scope": [
"email",
"profile"
]
}
}
}

View File

@ -4,10 +4,12 @@ import { AuthService } from './auth.service';
import { Request, Response } from 'express';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { GoogleOauthGuard } from 'src/google-oauth/google-oauth.guard';
import { User } from 'src/user/user.entity';
import { UserService } from 'src/user/user.service';
@ApiTags('Auth')
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) { }
constructor(private authService: AuthService, private userService: UserService) { }
@Post('login')
@ApiOperation({ summary: 'Login' })
@ -44,6 +46,23 @@ export class AuthController {
res.status(200).send(httpResponse);
}
@Post('signup')
async signup(@Body() userDto: User, @Res() res: Response) {
const user = await this.userService.findByEmail(userDto.email);
if (user) {
const errorResponse = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
exceptionMessage: 'ERR.NOT_FOUND',
stackTrace: 'User already exists'
}, null);
res.status(404).send(errorResponse);
}
const userCreated = await this.userService.upsert(userDto, true);
const tokens = await this.authService.login(userCreated);//MARK: NEED MAILER TO SEND CONFIRMATION EMAIL
const httpResponse = new GenericResponse(null, tokens);
res.status(200).send(httpResponse);
}
@Post('refresh')
async refresh(@Body() body: { refresh_token: string }, @Res() res: Response) {
const newToken = await this.authService.refreshAccessToken(body.refresh_token);

View File

@ -10,10 +10,10 @@ import { Request } from 'express';
@Injectable()
export class AuthService {
constructor(private userService: UserService, private jwtService: JwtService) { }
private async signToken(payload: any, type: 'accessToken' | 'refreshToken') {
private signToken(payload: any, type: 'accessToken' | 'refreshToken') {
const config = Utility.jwtConfig[type];
return this.jwtService.sign(payload, {
secret: config.secretOrKey,
@ -40,11 +40,19 @@ export class AuthService {
async login(user: any) {
const payload: JwtPayload = { email: user.email, password: user.password };
const accessToken = this.signToken(payload, 'accessToken');
const refreshToken = this.signToken(payload, 'refreshToken');
await RefreshToken.create({ email: user.email, token: refreshToken, type: 'jwt' });
return {
access_token: accessToken,
refresh_token: refreshToken,
};
}
async signup(user: any) {
const payload: JwtPayload = { email: user.email, password: user.password };
const accessToken = this.signToken(payload, 'accessToken');
const refreshToken = this.signToken(payload, 'refreshToken');
await RefreshToken.create({ email: user.email, token: refreshToken, type: 'jwt' });
return {
access_token: accessToken,
refresh_token: refreshToken,
@ -95,22 +103,24 @@ export class AuthService {
//google services
async googleOauthRedirect(user) {
console.log("user in service is",user);
if(!user.email) {
console.log("user in service is", user);
if (!user.email) {
return {
statusCode: 400,
message: 'User not found'
}
}
console.log("user.email in service is",user.email);
console.log("user.email in service is", user.email);
let existingUser = await User.findOne({ where: { email: user.email } });
if(!existingUser) {
if (!existingUser) {
existingUser = await User.create({
email: user.email,
name: user.name,});
name: user.name,
userTypeCode: 'user'
});
}
const payload = existingUser.get();
const accessToken = await this.signToken(payload, 'accessToken');
const refreshToken = await this.signToken(payload, 'refreshToken');

View File

@ -25,7 +25,7 @@ export class BookingGateway implements OnGatewayConnection, OnGatewayDisconnect
this.server.emit('clientsUpdated', this.connectedClients);
}
@SubscribeMessage('bookTciket')
@SubscribeMessage('bookTicket')
async handleBookTicket(@MessageBody() ticket: Ticket) {
const response = await this.bookingService.bookTicket(ticket);
this.server.to(ticket.eventId.toString() ).emit('ticketBooked', response);

View File

@ -0,0 +1,63 @@
import { Injectable } from '@nestjs/common';
import { diskStorage } from 'multer';
import { extname, join } from 'path';
import * as fs from 'fs';
@Injectable()
export class FilesService {
// Method to configure Multer's storage
getMulterStorage() {
return diskStorage({
destination: (req, file, cb) => {
// Define the upload path
const uploadPath = './uploads';
// Create the upload directory if it doesn't exist
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: true });
}
// Set the destination directory for file storage
cb(null, uploadPath);
},
filename: (req, file, cb) => {
// Generate a unique file name based on the current timestamp
const fileName = Date.now() + extname(file.originalname);
cb(null, fileName);
},
});
}
// Method to filter file types based on MIME type and extension
fileFilter(req, file, cb) {
const allowedImageTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'];
const allowedVideoTypes = ['video/mp4', 'video/avi', 'video/mov'];
// Check if the file is an image or a video
if (allowedImageTypes.includes(file.mimetype) || allowedVideoTypes.includes(file.mimetype)) {
return cb(null, true); // Allow the file
} else {
return cb(new Error('Only images (jpg, png, gif) and videos (mp4, avi, mov) are allowed!'), false); // Reject the file
}
}
// Helper method to categorize the uploaded files into images and videos
categorizeFiles(files: Express.Multer.File[]): { image: string[]; video: string[] } {
const categorizedFiles = {
image: [],
video: [],
};
// Categorize files based on their extensions
files.forEach(file => {
const ext = extname(file.originalname).toLowerCase();
if (['.jpg', '.jpeg', '.png', '.gif'].includes(ext)) {
categorizedFiles.image.push(file.path); // Categorize as image
} else if (['.mp4', '.avi', '.mov'].includes(ext)) {
categorizedFiles.video.push(file.path); // Categorize as video
}
});
return categorizedFiles;
}
}

View File

@ -1,14 +1,17 @@
import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, Post, Put, Res, UploadedFile, UploadedFiles, UseInterceptors } from '@nestjs/common';
import { EventService } from './event.service';
import { Response } from 'express';
import { GenericResponse } from '../common/GenericResponse.model';
import Event from './event.entity';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import path from 'path';
@ApiTags('event')
@Controller('event')
export class EventController {
constructor(private eventService: EventService) {}
constructor(private eventService: EventService) { }
@Get("/all")
@ApiOperation({ summary: 'Get all events' })
@ -31,7 +34,7 @@ export class EventController {
})
async getAllEvents(@Res() res: Response) {
const response = await this.eventService.findAll() || [];
if(!response) {
if (!response) {
const errorResponse = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
@ -178,8 +181,33 @@ export class EventController {
status: 201,
description: 'Successfully created a event',
})
async insert(@Body() event: Event, @Res() res: Response) {
if (!event) {
@UseInterceptors(FilesInterceptor('files', 10, {
storage: diskStorage({
destination: './uploads',
filename: (req, file, callback) => {
console.log(file);
const filename = file.originalname;
callback(null, filename);
}
})
}))
async insert(@Body() body: any, @Res() res: Response, @UploadedFiles() files?: Express.Multer.File[]) {
const event = JSON.parse(body.event)
console.log(event);
if (!files) {
console.log("No files");
}
if (!event.orgEmail) {
const response = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
exceptionMessage: 'ERR.MISSING_ORG_EMAIL',
stackTrace: 'Request'
}, null);
return res.status(400).send(response);
}
console.log(files);
if (!event || !files) {
const response = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
@ -188,6 +216,12 @@ export class EventController {
}, null);
return res.status(400).send(response);
}
const imageFiles = files.filter(file => file.mimetype.startsWith('image/')).map(file => file.filename);
const videoFiles = files.filter(file => file.mimetype.startsWith('video/')).map(file => file.filename);
event.images = {
images: imageFiles,
videos: videoFiles,
};
delete event.id;
const response = await this.eventService.upsert(event, true);
const httpResponse = new GenericResponse(null, response);

120
src/event/event.dto.ts Normal file
View File

@ -0,0 +1,120 @@
import { IsString, IsNumber, IsDate, IsOptional, IsEmail, IsArray, IsObject } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class EventDTO {
@ApiProperty({ type: String })
@IsEmail()
orgEmail: string;
@ApiProperty({ type: String })
@IsString()
eventName: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
startDate: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
endDate: Date;
@ApiProperty({ type: Number })
@IsNumber()
theatreId: number;
@ApiProperty({ type: String })
@IsString()
eventTime: string;
@ApiProperty({ type: String })
@IsString()
chiefGuests: string;
@ApiProperty({ type: String })
@IsString()
description: string;
@ApiProperty({ type: Object })
@IsObject()
images: object;
@ApiProperty({ type: String })
@IsString()
categories: string;
@ApiProperty({ type: Number })
@IsNumber()
ageRestriction: number;
@ApiProperty({ type: Number })
@IsNumber()
purchaseLimit: number;
@ApiProperty({ type: String })
@IsString()
cast: string;
@ApiProperty({ type: Number })
@IsNumber()
maxSeating: number;
@ApiProperty({ type: String })
@IsString()
eventType: string;
@ApiProperty({ type: String })
@IsString()
promoted: string;
@ApiProperty({ type: String })
@IsString()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
version: number;
}
export class EventUpdateDTO extends EventDTO {
@ApiProperty({ type: Number })
@IsNumber()
id: number;
}

View File

@ -0,0 +1,66 @@
import { IsString, IsNumber, IsDate, IsOptional, IsEmail, IsObject } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class EventAdditionalDetailDTO {
@ApiProperty({ type: Number })
@IsNumber()
eventsId: number;
@ApiProperty({ type: String })
@IsString()
addlDataType: string;
@ApiProperty({ type: String })
@IsString()
addlDataName: string;
@ApiProperty({ type: String })
@IsString()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
version: number;
}
export class EventAdditionalDetailUpdateDTO extends EventAdditionalDetailDTO {
@ApiProperty({ type: Number })
@IsNumber()
id: number;
}

View File

@ -10,7 +10,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
super({
clientID: Utility.googleOauthConfig.clientId,
clientSecret: Utility.googleOauthConfig.clientSecret,
callbackURL: Utility.googleOauthConfig.callbackUrl,
callbackURL: Utility.googleOauthConfig.callbackURL,
scope: Utility.googleOauthConfig.scope,
});
}

View File

@ -1,14 +1,15 @@
import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/common';
import { BadRequestException, Body, Controller, Delete, Get, Param, Post, Put, Res, UsePipes, ValidationPipe } from '@nestjs/common';
import { PayoutService } from './payout.service';
import { Response } from 'express';
import { GenericResponse } from '../common/GenericResponse.model';
import Payout from './payout.entity';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
import { PayoutDTO, PayoutUpdateDTO } from './payout.dto';
@ApiTags('payout')
@Controller('payout')
export class PayoutController {
constructor(private payoutService: PayoutService) {}
constructor(private payoutService: PayoutService) { }
@Get("/all")
@ApiOperation({ summary: 'Get all payouts' })
@ -30,8 +31,8 @@ export class PayoutController {
}
})
async getAllPayouts(@Res() res: Response) {
const response = await this.payoutService.findAll() || [];
if(!response) {
const response = await this.payoutService.findAll();
if (!response) {
const errorResponse = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
@ -87,7 +88,7 @@ export class PayoutController {
}, null);
return res.status(400).send(response);
}
const response = await this.payoutService.findByPk(id) || {};
const response = await this.payoutService.findByPk(id);
if (!response) {
const errorResponse = new GenericResponse({
exception: true,
@ -178,17 +179,18 @@ export class PayoutController {
status: 201,
description: 'Successfully created a payout',
})
async insert(@Body() payout: Payout, @Res() res: Response) {
@UsePipes(new ValidationPipe({ whitelist: true }))
async insert(@Body() payout: PayoutDTO, @Res() res: Response) {
console.log("Received payout:", payout);
if (!payout) {
const response = new GenericResponse({
exception: true,
exceptionSeverity: 'HIGH',
exceptionMessage: 'ERR.INVALID_DATA',
stackTrace: 'Request'
stackTrace: 'Request body is invalid'
}, null);
return res.status(400).send(response);
}
delete payout.id;
const response = await this.payoutService.upsert(payout, true);
const httpResponse = new GenericResponse(null, response);
res.status(201).send(httpResponse);
@ -227,7 +229,8 @@ export class PayoutController {
status: 200,
description: 'Successfully updated payout',
})
async update(@Body() payout: Payout, @Res() res: Response) {
@UsePipes(new ValidationPipe({ whitelist: true, skipMissingProperties: true }))
async update(@Body() payout: PayoutUpdateDTO, @Res() res: Response) {
if (!payout || !payout.id) {
const response = new GenericResponse({
exception: true,

88
src/payout/payout.dto.ts Normal file
View File

@ -0,0 +1,88 @@
import { IsString, IsEmail, IsNumber, IsDate, IsOptional, IsNotEmpty, IsEnum } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class PayoutDTO {
@ApiProperty({ type: String })
@IsEmail()
@IsNotEmpty()
payeeEmail: string;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
amount: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
paymentMethod: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
transactionId: string;
@ApiProperty({ type: String })
@IsEmail()
@IsNotEmpty()
paidToEmail: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
payoutDate: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class PayoutUpdateDTO extends PayoutDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

View File

@ -3,6 +3,7 @@ import Payout from './payout.entity';
import { firstValueFrom } from 'rxjs';
import { HttpService } from "@nestjs/axios";
import { Utility } from 'src/common/Utility';
import { PayoutDTO, PayoutUpdateDTO } from './payout.dto';
@Injectable()
export class PayoutService {
@ -32,16 +33,14 @@ export class PayoutService {
return Payout.destroy({ where: { id: id } });
}
async upsert(payout: Payout, insertIfNotFound: boolean): Promise<Payout | [affectedCount: number]> {
async upsert(payout: any, insertIfNotFound: boolean): Promise<Payout | [affectedCount: number]> {
if (payout.id) {
const existingPayout = await this.findByPk(payout.id);
if (existingPayout) {
return Payout.update(payout, { where: { id: payout.id } });
}
}
if (insertIfNotFound) {
//const textbookExists = await this.checkTextbookExists(payout.textbookId);
if (insertIfNotFound) {
return Payout.create(payout as any)
}
}

View File

@ -7,14 +7,14 @@ export class PushSubscriptionController {
constructor(private readonly pushSubscriptionService: PushSubscriptionService) { }
@Post('subscribe')
async subscribe(@Body() body: any) {
async subscribe(@Body() body: {endpoint: string, p256dh: string, auth: string}) {
console.log(body);
await this.pushSubscriptionService.saveSubscription(body);
return 'subscribed';
}
@Post('send-notification')
async sendNotification(@Body() body: any) {
async sendNotification(@Body() body: { title: string, message: string }) {
await this.pushSubscriptionService.sendPushNotification(body.title, body.message);
return 'notification sent';
}

View File

@ -1,6 +1,6 @@
import * as webPush from 'web-push';
import { Injectable } from '@nestjs/common';
import PushSubscription from './push-subscription.entity';
import PushSubscription from './push-subscription.entity';
import { Utility } from 'src/common/Utility';
@Injectable()
@ -19,25 +19,24 @@ export class PushSubscriptionService {
return 'saved subscription';
}
async sendPushNotification(title: any, message: any) {
const subs = await PushSubscription.findAll();
var pushSub: any;
for (const sub of subs) {
pushSub = {
async sendPushNotification(title: string, message: string) {
const subscriptions = await PushSubscription.findAll();
const payload = JSON.stringify({ title, message });
for (const sub of subscriptions) {
const pushSub = {
endpoint: sub.endpoint,
keys: {
p256dh: sub.p256dh,
auth: sub.auth,
},
};
}
const payload = JSON.stringify({ title, message })
try {
await webPush.sendPushNotification(pushSub, payload)
} catch (err) {
console.log("error occurred", err)
try {
await webPush.sendNotification(pushSub, payload);
} catch (err) {
console.error('Error sending push notification', err);
}
}
}
}
}

View File

@ -1,36 +1,66 @@
import { Controller, Get, Param, Post, Body, Delete } from '@nestjs/common';
import { RedisService } from './redis.service';
import { BadRequestException, InternalServerErrorException } from '@nestjs/common';
import { Logger } from '@nestjs/common';
@Controller('redis')
export class RedisController {
constructor(private readonly redisService: RedisService) { }
private readonly logger = new Logger(RedisController.name);
constructor(private readonly redisService: RedisService) {}
@Post('set')
async setValue(@Body() body: { key: string, value: string, ttl?: number }) {
if (body.ttl) {
await this.redisService.setTimed(body.key, body.value, body.ttl);
async setValue(@Body() body: { key: string; value: string; ttl?: number }) {
if (body.ttl && body.ttl <= 0) {
throw new BadRequestException('TTL must be a positive number');
}
else {
await this.redisService.set(body.key, body.value);
try {
if (body.ttl) {
await this.redisService.setTimed(body.key, body.value, body.ttl);
} else {
await this.redisService.set(body.key, body.value);
}
return { success: true, message: 'Value set in Redis' };
} catch (error) {
this.logger.error('Failed to set value in Redis', error.stack);
throw new InternalServerErrorException('Failed to set value in Redis');
}
return { message: 'Value set in Redis' };
}
@Get('get/:key')
async getValue(@Param('key') key: string) {
const value = await this.redisService.get(key);
return { value };
try {
const value = await this.redisService.get(key);
if (value === null) {
throw new BadRequestException('Key not found');
}
return { success: true, value };
} catch (error) {
this.logger.error('Failed to get value from Redis', error.stack);
throw new InternalServerErrorException('Failed to get value from Redis');
}
}
@Delete('del/:key')
async deleteValue(@Param('key') key: string) {
await this.redisService.del(key);
return { message: 'Value deleted from Redis' };
try {
await this.redisService.del(key);
return { success: true, message: 'Value deleted from Redis' };
} catch (error) {
this.logger.error('Failed to delete value from Redis', error.stack);
throw new InternalServerErrorException('Failed to delete value from Redis');
}
}
@Delete('flushall')
async flushall() {
await this.redisService.flushall();
return { message: 'Redis flushed' };
@Get('flushall')
async flushAll() {
try {
await this.redisService.flushall();
return { success: true, message: 'Redis flushed' };
} catch (error) {
this.logger.error('Failed to flush Redis', error.stack);
throw new InternalServerErrorException('Failed to flush Redis');
}
}
}

View File

@ -6,6 +6,6 @@ import { RedisService } from './redis.service';
@Module({
controllers: [RedisController],
providers: [RedisService, RedisProvider],
exports: [RedisProvider],
exports: [RedisProvider, RedisService],
})
export class RedisModule { }

View File

@ -5,7 +5,7 @@ import { RedisProvider } from './redis.provider';
export class RedisService {
constructor(private readonly redisProvider: RedisProvider) {}
async set(key: string, value: string): Promise<void> {
async set(key: string, value: any): Promise<void> {
const client = this.redisProvider.client;
await client.set(key, value, );
}
@ -20,7 +20,7 @@ export class RedisService {
await client.flushall();
}
async setTimed(key: string, value: string, ttl: number): Promise<void> {
async setTimed(key: string, value: any, ttl: number): Promise<void> {
const client = this.redisProvider.client;
await client.set(key, value, 'EX', ttl);
}

83
src/refund/refund.dto.ts Normal file
View File

@ -0,0 +1,83 @@
import { IsString, IsNumber, IsDate, IsOptional, IsNotEmpty, IsEmail } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class RefundDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
ticketId: number;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
refundAmount: number;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
refundPercentage: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
refundReason: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
refundDate: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class RefundUpdateDTO extends RefundDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

79
src/review/review.dto.ts Normal file
View File

@ -0,0 +1,79 @@
import { IsString, IsNumber, IsDate, IsNotEmpty, IsOptional, IsEmail } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class ReviewDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
eventId: number;
@ApiProperty({ type: String })
@IsEmail()
@IsNotEmpty()
buyerEmail: string;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
rating: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
comment: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class ReviewUpdateDTO extends ReviewDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number;
}

View File

@ -4,11 +4,12 @@ import { Response } from 'express';
import { GenericResponse } from '../common/GenericResponse.model';
import Seat from './seat.entity';
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiBody } from '@nestjs/swagger';
import { RedisService } from 'src/redis/redis.service';
@ApiTags('seat')
@Controller('seat')
export class SeatController {
constructor(private seatService: SeatService) {}
constructor(private seatService: SeatService, private redisService: RedisService) {}
@Get("/all")
@ApiOperation({ summary: 'Get all seats' })
@ -30,7 +31,12 @@ export class SeatController {
}
})
async getAllSeats(@Res() res: Response) {
const response = await this.seatService.findAll() || [];
// const cacheKey = 'all_seats';
// let response = await this.redisService.get(cacheKey);
// if (!response) {
const response = await this.seatService.findAll() || [];
// await this.redisService.setTimed(cacheKey, seats,300);
// }
if(!response) {
const errorResponse = new GenericResponse({
exception: true,

84
src/seat/seat.dto.ts Normal file
View File

@ -0,0 +1,84 @@
import { IsString, IsNumber, IsDate, IsNotEmpty, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class SeatDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
eventId: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
seatNumber: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
row: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
column: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
available: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class SeatUpdateDTO extends SeatDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number;
}

View File

@ -2,9 +2,13 @@ import { Module } from '@nestjs/common';
import { SeatController } from './seat.controller';
import { SeatService } from './seat.service';
import { HttpModule } from '@nestjs/axios';
// import { RedisService } from 'src/redis/redis.service';
// import { RedisProvider } from 'src/redis/redis.provider';
// import Redis from 'ioredis';
import { RedisModule } from 'src/redis/redis.module';
@Module({
imports: [HttpModule],
imports: [HttpModule, RedisModule],
providers: [SeatService],
controllers: [SeatController],
})

View File

@ -31,7 +31,7 @@ export class SeatService {
}
async bookSeat(eventId: number, seatNumber: string) {
return Seat.update({ awailable: 'booked' }, { where: { eventId: eventId, seatNumber: seatNumber } });
return Seat.update({ available: 'booked' }, { where: { eventId: eventId, seatNumber: seatNumber } });
}
async upsert(seat: Seat, insertIfNotFound: boolean): Promise<Seat | [affectedCount: number]> {

View File

@ -0,0 +1,94 @@
import { IsString, IsNumber, IsDate, IsNotEmpty, IsOptional, IsObject } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class TheatreDTO {
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
theatreName: string;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
rows: number;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
columns: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
address: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
city: string;
@ApiProperty({ type: Object })
@IsObject()
@IsNotEmpty()
images: object;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
totalSeats: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class TheatreUpdateDTO extends TheatreDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

View File

@ -0,0 +1,74 @@
import { IsString, IsNumber, IsDate, IsNotEmpty, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class TheatreAdditionalDetailsDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
theatreId: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
addlDataType: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
addlDataName: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class TheatreAdditionalDetailsUpdateDTO extends TheatreAdditionalDetailsDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number;
}

110
src/ticket/ticket.dto.ts Normal file
View File

@ -0,0 +1,110 @@
import { IsString, IsNumber, IsDate, IsNotEmpty, IsEmail, IsOptional } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class TicketDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
eventId: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
ticketType: string;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
price: number;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
seatNumber: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
qrCode: string;
@ApiProperty({ type: String })
@IsEmail()
@IsNotEmpty()
buyerEmail: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
bookingDate: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
paymentStatus: string;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
rescheduledAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
scanned: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class TicketUpdateDTO extends TicketDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

View File

@ -0,0 +1,76 @@
import { IsString, IsNumber, IsDate, IsOptional, IsNotEmpty } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class TimeSlotDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
eventId: number;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
startTime: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
endTime: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class TimeSlotUpdateDTO extends TimeSlotDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

View File

@ -0,0 +1,76 @@
import { IsString, IsNumber, IsDate, IsOptional, IsNotEmpty } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
export class TimeSlotDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
eventId: number;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
startTime: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
endTime: Date;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class TimeSlotUpdateDTO extends TimeSlotDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

90
src/user/user.dto.ts Normal file
View File

@ -0,0 +1,90 @@
import { IsString, IsEmail, IsOptional, IsNotEmpty, IsDate, IsNumber } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import UserAdditionalDetail from './user-additional-details/user-additional-details.entity';
export class UserDTO {
@ApiProperty({ type: String })
@IsEmail()
@IsNotEmpty()
email: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
password: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
userTypeCode: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
name: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
phoneNumber: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
primaryRole: string;
@ApiProperty({ type: String })
@IsString()
@IsNotEmpty()
status: string;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validFrom: Date;
@ApiProperty({ type: Date })
@IsDate()
@IsNotEmpty()
@Transform(({ value }) => new Date(value))
validTill: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
createdAt: Date;
@ApiProperty({ type: Date })
@IsDate()
@Transform(({ value }) => new Date(value))
updatedAt: Date;
@ApiProperty({ type: String })
@IsString()
createdBy: string;
@ApiProperty({ type: String })
@IsString()
modifiedBy: string;
@ApiProperty({ type: Date })
@IsOptional()
@IsDate()
@Transform(({ value }) => value ? new Date(value) : null)
deletedAt: Date;
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
version: number;
}
export class UserUpdateDTO extends UserDTO {
@ApiProperty({ type: Number })
@IsNumber()
@IsNotEmpty()
id: number
}

View File

@ -23,7 +23,7 @@ export class UserService {
}
filter(user: User) : Promise<User[]> {
return User.findAll({where: user as any, include: UserAdditionalDetail})
return User.findAll({where: user as any})
}
async remove(id: number): Promise<number> {