diff --git a/.eslintrc.js b/.eslintrc.js index 259de13..a62bafb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -9,6 +9,7 @@ module.exports = { extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', + "prettier" ], root: true, env: { diff --git a/.gitignore b/.gitignore index a30d993..e8832e2 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,4 @@ lerna-debug.log* # environment .env +package-lock.json \ No newline at end of file diff --git a/package.json b/package.json index 03b8523..153c82c 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "haqdarshak-customer-app", + "name": "event-management-app", "version": "0.0.1", "description": "", "author": "", @@ -30,7 +30,6 @@ "axios": "^1.6.2", "class-transformer": "^0.5.1", "class-validator": "^0.14.1", - "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1" }, @@ -46,7 +45,7 @@ "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", - "eslint-config-prettier": "^9.0.0", + "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", diff --git a/src/app.module.ts b/src/app.module.ts index 770da09..a7ce318 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -16,4 +16,4 @@ import { AttendeesModule } from './modules/attendees/attendees.module'; controllers: [AppController], providers: [AppService], }) -export class AppModule { } +export class AppModule {} diff --git a/src/common/database-modules.ts b/src/common/database-modules.ts index 7e01b0c..a81e7b7 100644 --- a/src/common/database-modules.ts +++ b/src/common/database-modules.ts @@ -2,17 +2,19 @@ import { Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { TypeOrmModule } from '@nestjs/typeorm'; - @Module({ imports: [ TypeOrmModule.forRootAsync({ useFactory: (configService: ConfigService) => ({ - type: 'postgres', + type: 'postgres', host: configService.get('POSTGRES_HOST'), port: configService.get('POSTGRES_PORT'), database: configService.get('POSTGRES_DATABASE'), username: configService.get('POSTGRES_USERNAME'), password: configService.get('POSTGRES_PASSWORD'), + extra: { + timezone: 'Z', // Use "Z" for UTC or your preferred timezone + }, // entities: [ // User // ], @@ -23,4 +25,4 @@ import { TypeOrmModule } from '@nestjs/typeorm'; ], providers: [ConfigService], }) -export class DatabaseModule {} \ No newline at end of file +export class DatabaseModule {} diff --git a/src/common/filters/exception.filter.ts b/src/common/filters/exception.filter.ts index 3bcf02f..5b6811f 100644 --- a/src/common/filters/exception.filter.ts +++ b/src/common/filters/exception.filter.ts @@ -1,29 +1,38 @@ -import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'; -import { Response, Request } from 'express'; +import { + ExceptionFilter, + Catch, + ArgumentsHost, + HttpException, +} from '@nestjs/common'; +import { Response } from 'express'; import APIResponse from '../utils/response'; import { ERROR_MESSAGES } from '../utils/constants.util'; @Catch() export class AllExceptionsFilter implements ExceptionFilter { - constructor(private readonly apiId?: string) { } + constructor(private readonly apiId?: string) {} - catch(exception: unknown, host: ArgumentsHost) { - const ctx = host.switchToHttp(); - const response = ctx.getResponse(); - const status = exception instanceof HttpException ? exception.getStatus() : 500; - const exceptionResponse = exception instanceof HttpException ? exception.getResponse() : null; - const errorMessage = - exception instanceof HttpException - ? (exceptionResponse as any).message || exception.message - : ERROR_MESSAGES.INTERNAL_SERVER_ERROR; - const detailedErrorMessage = `${errorMessage}`; - console.log('detailedErrorMessage', detailedErrorMessage); - const errorResponse = APIResponse.error( - this.apiId, - detailedErrorMessage, - exception instanceof HttpException ? exception.name : ERROR_MESSAGES.INTERNAL_SERVER_ERROR, // error - status.toString(), - ); - return response.status(status).json(errorResponse); - } + catch(exception: unknown, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + const status = + exception instanceof HttpException ? exception.getStatus() : 500; + const exceptionResponse = + exception instanceof HttpException ? exception.getResponse() : null; + const errorMessage = + exception instanceof HttpException + ? (exceptionResponse as any).message || exception.message + : ERROR_MESSAGES.INTERNAL_SERVER_ERROR; + const detailedErrorMessage = `${errorMessage}`; + console.log('detailedErrorMessage', detailedErrorMessage); + const errorResponse = APIResponse.error( + this.apiId, + detailedErrorMessage, + exception instanceof HttpException + ? exception.name + : ERROR_MESSAGES.INTERNAL_SERVER_ERROR, + status.toString(), + ); + return response.status(status).json(errorResponse); + } } diff --git a/src/common/pipes/event-validation.pipe.ts b/src/common/pipes/event-validation.pipe.ts index 885f237..ac1342b 100644 --- a/src/common/pipes/event-validation.pipe.ts +++ b/src/common/pipes/event-validation.pipe.ts @@ -1,28 +1,15 @@ import { ConfigService } from '@nestjs/config'; -import { - PipeTransform, - Injectable, - BadRequestException, - forwardRef, - Inject, -} from '@nestjs/common'; +import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; import { CreateEventDto } from 'src/modules/event/dto/create-event.dto'; import { getTimezoneDate } from '../utils/pipe.util'; -import { get } from 'http'; import { ERROR_MESSAGES } from '../utils/constants.util'; -import { - ValidatorConstraint, - ValidatorConstraintInterface, - ValidationArguments, -} from 'class-validator'; + @Injectable() export class DateValidationPipe implements PipeTransform { - // constructor(@Inject(forwardRef(() => ConfigService)) private configService: ConfigService) { - - // } + constructor(private configService: ConfigService) {} transform(createEventDto: CreateEventDto) { - const timeZone = 'Asia/Kolkata'; + const timeZone = this.configService.get('TIMEZONE'); const startDate = getTimezoneDate( timeZone, new Date(createEventDto.startDatetime), @@ -31,14 +18,7 @@ export class DateValidationPipe implements PipeTransform { timeZone, new Date(createEventDto.endDatetime), ); - const currentDate = getTimezoneDate(timeZone); // Current date - // this.configService.get('TIMEZONE'); // Get the timezone from the config service - - console.log('currentDate', currentDate); - console.log('startDate', startDate); - console.log('endDate', endDate); - - console.log(startDate <= currentDate, 'startDate <= currentDate'); + const currentDate = getTimezoneDate(timeZone); // Current date in the specified timezone if (startDate <= currentDate) { throw new BadRequestException( @@ -56,8 +36,10 @@ export class DateValidationPipe implements PipeTransform { @Injectable() export class RegistrationDateValidationPipe implements PipeTransform { + constructor(private configService: ConfigService) {} + transform(createEventDto: CreateEventDto) { - const timeZone = 'Asia/Kolkata'; + const timeZone = this.configService.get('TIMEZONE'); const currentDate = getTimezoneDate(timeZone); const startDate = getTimezoneDate( timeZone, @@ -69,35 +51,21 @@ export class RegistrationDateValidationPipe implements PipeTransform { ); const registrationStartDate = createEventDto.registrationEndDate ? getTimezoneDate( - timeZone, - new Date(createEventDto.registrationStartDate), - ) + timeZone, + new Date(createEventDto.registrationStartDate), + ) : null; const isRestricted = createEventDto.isRestricted; const registrationEndDate = createEventDto.registrationEndDate ? getTimezoneDate(timeZone, new Date(createEventDto.registrationEndDate)) : null; - console.log( - registrationStartDate, - 'rrrrr', - startDate, - registrationStartDate > startDate, - registrationStartDate < startDate, - ); - console.log( - createEventDto.isRestricted && registrationStartDate, - 'createEventDto.isRestricted && registrationStartDate ', - ); - console.log( - createEventDto.isRestricted && registrationEndDate, - 'createEventDto.isRestricted && registrationEndDate', - ); + // Ensure registration dates are not provided for restricted events + if ( (createEventDto.isRestricted && registrationStartDate) || (createEventDto.isRestricted && registrationEndDate) ) { - console.log(''); throw new BadRequestException( ERROR_MESSAGES.RESTRICTED_EVENT_NO_REGISTRATION_DATE, ); @@ -141,12 +109,14 @@ export class RegistrationDateValidationPipe implements PipeTransform { } export class RecurringEndDateValidationPipe implements PipeTransform { + constructor(private configService: ConfigService) {} + transform(createEventDto: CreateEventDto) { - const currentDate = getTimezoneDate('Asia/Kolkata'); + const timeZone = this.configService.get('TIMEZONE'); if (createEventDto.isRecurring) { const recurrenceEndDate = new Date(createEventDto.recurrenceEndDate); const startDate = new Date(createEventDto.startDatetime); - + const currentDate = getTimezoneDate(timeZone); if (recurrenceEndDate < currentDate) { throw new BadRequestException( ERROR_MESSAGES.RECURRENCE_END_DATE_INVALID, diff --git a/src/common/utils/constants.util.ts b/src/common/utils/constants.util.ts index 9dbf90a..1ded11b 100644 --- a/src/common/utils/constants.util.ts +++ b/src/common/utils/constants.util.ts @@ -1,56 +1,68 @@ export const ERROR_MESSAGES = { - INVALID_REQUEST: 'Invalid request', - NOT_FOUND: 'Not found', - UNAUTHORIZED: 'Unauthorized', - FORBIDDEN: 'Forbidden', - BAD_REQUEST: 'Bad request', - INVALID_REQUEST_BODY: 'Invalid request body', - INTERNAL_SERVER_ERROR: 'Internal Server Error', - REGISTRATION_DATE_INVALID: 'Registration date must be in the future', - REGISTRATION_START_DATE_BEFORE_EVENT_DATE: 'Registration start date must be before the event start date', - REGISTRATION_END_DATE_BEFORE_EVENT_DATE: 'Registration end date must be on or before the event start date', - REGISTRATION_START_DATE_INVALID: 'Registration start date must be in the future', - REGISTRATION_END_DATE_INVALID: 'Registration end date must be in the future', - REGISTRATION_START_DATE_BEFORE_END_DATE: 'Registration start date must be before registration end date', - RECURRENCE_END_DATE_INVALID: 'Recurrence end date must be in the future', - RECURRENCE_END_DATE_BEFORE_EVENT_DATE: 'Recurrence end date must be after the event start date', - RECURRING_PATTERN_REQUIRED: 'Recurrence Pattern required for event', - REGISTRATION_START_DATE_REQUIRED: 'Registration Start Date required for event', - INVITEES_REQUIRED: 'Invitees required for private event', - INVITEES_NOT_REQUIRED: 'Invitees not required for public event', - EVENT_NOT_FOUND: 'Event not found', - EVENT_ATTENDEE_NOT_FOUND: 'Event attendee not found', - EVENT_ATTENDEE_HISTORY_NOT_FOUND: 'Event attendee history not found', - EVENT_ATTENDEE_HISTORY_ITEM_NOT_FOUND: 'Event attendee history item not found', -} + INVALID_REQUEST: 'Invalid request', + NOT_FOUND: 'Not found', + UNAUTHORIZED: 'Unauthorized', + FORBIDDEN: 'Forbidden', + BAD_REQUEST: 'Bad request', + INVALID_REQUEST_BODY: 'Invalid request body', + INTERNAL_SERVER_ERROR: 'Internal Server Error', + REGISTRATION_DATE_INVALID: 'Registration date must be in the future', + REGISTRATION_START_DATE_BEFORE_EVENT_DATE: + 'Registration start date must be before the event start date', + REGISTRATION_END_DATE_BEFORE_EVENT_DATE: + 'Registration end date must be on or before the event start date', + REGISTRATION_START_DATE_INVALID: + 'Registration start date must be in the future', + REGISTRATION_END_DATE_INVALID: 'Registration end date must be in the future', + REGISTRATION_START_DATE_BEFORE_END_DATE: + 'Registration start date must be before registration end date', + RECURRENCE_END_DATE_INVALID: 'Recurrence end date must be in the future', + RECURRENCE_END_DATE_BEFORE_EVENT_DATE: + 'Recurrence end date must be after the event start date', + RECURRING_PATTERN_REQUIRED: 'Recurrence Pattern required for event', + REGISTRATION_START_DATE_REQUIRED: + 'Registration Start Date required for event', + RESTRICTED_EVENT_NO_REGISTRATION_DATE: + 'Cannot have registration date for restricted event', + INVITEES_REQUIRED: 'Invitees required for private event', + INVITEES_NOT_REQUIRED: 'Invitees not required for public event', + EVENT_NOT_FOUND: 'Event not found', + EVENT_ATTENDEE_NOT_FOUND: 'Event attendee not found', + EVENT_ATTENDEE_HISTORY_NOT_FOUND: 'Event attendee history not found', + EVENT_ATTENDEE_HISTORY_ITEM_NOT_FOUND: + 'Event attendee history item not found', +}; export const SUCCESS_MESSAGES = { - EVENT_CREATED: 'Event created successfully', - EVENT_UPDATED: 'Event updated successfully', - EVENT_DELETED: 'Event deleted successfully', - EVENT_NOT_FOUND: 'Event not found', - EVENT_ATTENDEE_CREATED: 'Event attendee created successfully', - EVENT_ATTENDEE_UPDATED: 'Event attendee updated successfully', - EVENT_ATTENDEE_DELETED: 'Event attendee deleted successfully', - EVENT_ATTENDEE_HISTORY_ITEM_CREATED: 'Event attendee history item created successfully', - EVENT_ATTENDEE_HISTORY_ITEM_UPDATED: 'Event attendee history item updated successfully', - EVENT_ATTENDEE_HISTORY_ITEM_DELETED: 'Event attendee history item deleted successfully', -} + EVENT_CREATED: 'Event created successfully', + EVENT_UPDATED: 'Event updated successfully', + EVENT_DELETED: 'Event deleted successfully', + EVENT_NOT_FOUND: 'Event not found', + EVENT_ATTENDEE_CREATED: 'Event attendee created successfully', + EVENT_ATTENDEE_UPDATED: 'Event attendee updated successfully', + EVENT_ATTENDEE_DELETED: 'Event attendee deleted successfully', + EVENT_ATTENDEE_HISTORY_ITEM_CREATED: + 'Event attendee history item created successfully', + EVENT_ATTENDEE_HISTORY_ITEM_UPDATED: + 'Event attendee history item updated successfully', + EVENT_ATTENDEE_HISTORY_ITEM_DELETED: + 'Event attendee history item deleted successfully', +}; export const API_ID = { - CREATE_EVENT: 'api.event.create', - GET_EVENT_BY_ID: 'api.event.getbyid', - GET_EVENTS: 'api.events.get', - UPDATE_EVENT: 'api.event.update', - DELETE_EVENT: 'api.event.delete', - GET_EVENT_ATTENDEES: 'api.event.attendees.get', - GET_EVENT_ATTENDEE: 'api.event.attendee.get', - CREATE_EVENT_ATTENDEE: 'api.event.attendee.create', - UPDATE_EVENT_ATTENDEE: 'api.event.attendee.update', - DELETE_EVENT_ATTENDEE: 'api.event.attendee.delete', - GET_EVENT_ATTENDEE_HISTORY: 'api.event.attendee.history.get', - GET_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.get', - CREATE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.create', - UPDATE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.update', - DELETE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.delete', -} \ No newline at end of file + CREATE_EVENT: 'api.event.create', + GET_EVENT_BY_ID: 'api.event.getbyid', + GET_EVENTS: 'api.events.get', + UPDATE_EVENT: 'api.event.update', + DELETE_EVENT: 'api.event.delete', + GET_EVENT_ATTENDEES: 'api.event.attendees.get', + GET_EVENT_ATTENDEE: 'api.event.attendee.get', + CREATE_EVENT_ATTENDEE: 'api.event.attendee.create', + UPDATE_EVENT_ATTENDEE: 'api.event.attendee.update', + DELETE_EVENT_ATTENDEE: 'api.event.attendee.delete', + GET_EVENT_ATTENDEE_HISTORY: 'api.event.attendee.history.get', + GET_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.get', + CREATE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.create', + UPDATE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.update', + DELETE_EVENT_ATTENDEE_HISTORY_ITEM: 'api.event.attendee.history.item.delete', +}; diff --git a/src/common/utils/transformer/date.transformer.ts b/src/common/utils/transformer/date.transformer.ts new file mode 100644 index 0000000..6ace651 --- /dev/null +++ b/src/common/utils/transformer/date.transformer.ts @@ -0,0 +1,25 @@ +import { ConfigService } from '@nestjs/config'; +import { getTimezoneDate } from 'src/common/utils/pipe.util'; +import { ValueTransformer } from 'typeorm'; + +export class TimeZoneTransformer implements ValueTransformer { + // private timeZone: string; + + constructor(private configService: ConfigService) {} + + // To DB: Convert the date to UTC before saving + to(entityValue: Date): Date { + // if (!entityValue) return entityValue; + return entityValue; + } + + // From DB: Convert the date from UTC to the desired time zone after fetching + from(databaseValue: Date): Date { + if (!databaseValue) return databaseValue; + return getTimezoneDate( + this.configService.get('TIMEZONE'), + new Date(databaseValue), + ); + } +} + diff --git a/src/modules/attendees/entity/attendees.entity.ts b/src/modules/attendees/entity/attendees.entity.ts index 0da6599..34fdeaa 100644 --- a/src/modules/attendees/entity/attendees.entity.ts +++ b/src/modules/attendees/entity/attendees.entity.ts @@ -1,49 +1,68 @@ -import { Users } from 'src/modules/event/entities/Users.entity'; +import { ConfigService } from '@nestjs/config'; +import { TimeZoneTransformer } from 'src/common/utils/transformer/date.transformer'; import { Events } from 'src/modules/event/entities/event.entity'; -import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, OneToMany, CreateDateColumn, JoinColumn, UpdateDateColumn } from 'typeorm'; +import { + Entity, + Column, + PrimaryGeneratedColumn, + ManyToOne, + OneToMany, + CreateDateColumn, + JoinColumn, + UpdateDateColumn, +} from 'typeorm'; @Entity('EventAttendees') export class EventAttendees { + @PrimaryGeneratedColumn('uuid') + eventAttendeesId: string; - @PrimaryGeneratedColumn('uuid') - eventAttendeesId: string; + @Column({ type: 'uuid', nullable: true }) + eventRepetitionId: string; - @Column({ type: 'uuid' }) - userId: string; + @Column({ type: 'int', nullable: false, default: 0 }) + duration: number; - @Column({ type: 'uuid' }) - eventId: string; + @Column({ type: 'varchar', nullable: true, collation: 'pg_catalog.default' }) + status: string; - @Column({ nullable: true, default: null }) - isAttended: boolean | null; + @Column({ type: 'timestamptz', nullable: true, + transformer: new TimeZoneTransformer(new ConfigService()) + }) + enrolledAt: Date; - @Column({ type: 'jsonb', nullable: true }) - joinedLeftHistory: any; + @Column({ type: 'uuid', nullable: true }) + enrolledBy: string; - @Column({ nullable: false, default: 0 }) - duration: number; + @UpdateDateColumn({ type: 'timestamptz', transformer: new TimeZoneTransformer(new ConfigService()) }) + updatedAt: Date; - @Column() - status: string; + @Column({ type: 'uuid', nullable: true }) + updatedBy: string; - @CreateDateColumn({ type: 'timestamp' }) - enrolledAt: Date; + @CreateDateColumn({ type: 'timestamptz', transformer: new TimeZoneTransformer(new ConfigService()) }) + createdAt: Date; - @Column({ type: 'uuid', nullable: true }) - enrolledBy: string; + @Column({ type: 'uuid', nullable: true }) + createdBy: string; - @UpdateDateColumn({ type: 'timestamp' }) - updatedAt: Date; + @Column({ type: 'uuid' }) + userId: string; - @Column({ type: 'uuid', nullable: true }) - updatedBy: string; + @Column({ type: 'uuid' }) + eventId: string; - @ManyToOne(() => Events, event => event.eventAttendees) - @JoinColumn({ name: 'eventId' }) - event: Events; + @Column({ nullable: true, default: null }) + isAttended: boolean | null; - @ManyToOne(() => Users, user => user.eventAttendees) - @JoinColumn({ name: 'userId' }) - user: Users; + @Column({ type: 'jsonb', nullable: true }) + joinedLeftHistory: any; -} \ No newline at end of file + // @ManyToOne(() => Events, event => event.eventAttendees) + // @JoinColumn({ name: 'eventId' }) + // event: Events; + + // @ManyToOne(() => Users, user => user.eventAttendees) + // @JoinColumn({ name: 'userId' }) + // user: Users; +} diff --git a/src/modules/event/entities/event.entity.ts b/src/modules/event/entities/event.entity.ts index e53891f..e612abd 100644 --- a/src/modules/event/entities/event.entity.ts +++ b/src/modules/event/entities/event.entity.ts @@ -1,78 +1,83 @@ -import { EventAttendees } from 'src/modules/attendees/entity/attendees.entity'; -import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, OneToMany, ManyToOne } from 'typeorm'; +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, + OneToMany, + OneToOne, +} from 'typeorm'; +import { EventDetail } from './eventDetail.entity'; +import { EventRepetition } from './eventRepetition.entity'; +import { TimeZoneTransformer } from '../../../common/utils/transformer/date.transformer'; +import { ConfigService } from '@nestjs/config'; @Entity('Events') export class Events { - @PrimaryGeneratedColumn('uuid') - eventID: string; - - @Column({ nullable: false }) - title: string; - - @Column({ nullable: false }) - shortDescription: string; - - @Column({ nullable: false }) - description: string; - - @Column({ nullable: false }) - image: string; - - @Column({ nullable: false }) - eventType: string; - - @Column({ nullable: false, default: false }) - isRestricted: boolean; - - @Column({ default: false }) - autoEnroll: boolean; - - @Column({ nullable: false, type: 'timestamp' }) - startDatetime: Date; - - @Column({ nullable: false, type: 'timestamp' }) - endDatetime: Date; - - @Column({ nullable: false }) - location: string; - - @Column({ nullable: false, type: 'double precision' }) - longitude: number; - - @Column({ nullable: false, type: 'double precision' }) - latitude: number; - - @Column({ nullable: false }) - onlineProvider: string; - - @Column({ nullable: false, type: 'timestamp' }) - registrationDeadline: Date; - - @Column({ nullable: false, default: 0 }) - maxAttendees: number; - - @Column({ nullable: false, type: 'json' }) - params: any; - - @Column({ nullable: false, type: 'json' }) - recordings: any; - - @Column({ nullable: false }) - status: string; - - @Column({ nullable: false }) - createdBy: string; - - @Column({ nullable: false }) - updatedBy: string; - - - @CreateDateColumn({ type: 'timestamp' }) - createdAt: Date; - - @UpdateDateColumn({ type: 'timestamp' }) - updatedAt: Date; - - @OneToMany(() => EventAttendees, eventAttendees => eventAttendees.event, { cascade: true }) - eventAttendees: EventAttendees[]; - + @PrimaryGeneratedColumn('uuid') + eventId: string; + + @Column({ type: 'boolean', default: false }) + isRecurring: boolean; + + @Column({ + type: 'timestamptz', + transformer: new TimeZoneTransformer(new ConfigService()), + }) + recurrenceEndDate: Date; + + @Column({ type: 'jsonb' }) + recurrencePattern: object; + + @CreateDateColumn({ + type: 'timestamptz', + default: () => 'CURRENT_TIMESTAMP', + transformer: new TimeZoneTransformer(new ConfigService()), + }) + createdAt: Date; + + @UpdateDateColumn({ + type: 'timestamptz', + default: () => 'CURRENT_TIMESTAMP', + transformer: new TimeZoneTransformer(new ConfigService()), + }) + updatedAt: Date; + + @Column({ type: 'boolean', default: false }) + autoEnroll: boolean; + + @Column({ + type: 'timestamptz', + nullable: true, + transformer: new TimeZoneTransformer(new ConfigService()), + }) + registrationStartDate: Date; + + @Column({ + type: 'timestamptz', + nullable: true, + transformer: new TimeZoneTransformer(new ConfigService()), + }) + registrationEndDate: Date; + + @Column({ type: 'uuid', nullable: true }) + createdBy: string; + + @Column({ type: 'uuid', nullable: true }) + updatedBy: string; + + @Column({ type: 'uuid' }) + eventDetailId: string; + + // OR onetomany + @OneToOne(() => EventDetail, (eventDetail) => eventDetail.events, { + onDelete: 'CASCADE', + onUpdate: 'CASCADE', + }) + @JoinColumn({ name: 'eventDetailId' }) + eventDetail: EventDetail; + + // @OneToMany(() => EventRepetition, (eventRepetition) => eventRepetition.event) + // eventRepetitions: EventRepetition[]; } diff --git a/src/modules/event/entities/eventDetail.entity.ts b/src/modules/event/entities/eventDetail.entity.ts new file mode 100644 index 0000000..0613b94 --- /dev/null +++ b/src/modules/event/entities/eventDetail.entity.ts @@ -0,0 +1,95 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + OneToMany, +} from 'typeorm'; +import { Events } from './event.entity'; +import { EventRepetition } from './eventRepetition.entity'; +import { TimeZoneTransformer } from '../../../common/utils/transformer/date.transformer'; +import { ConfigService } from '@nestjs/config'; + +@Entity('EventDetails') +export class EventDetail { + @PrimaryGeneratedColumn('uuid') + eventDetailId: string; + + @Column({ type: 'varchar', length: 255 }) + title: string; + + @Column({ type: 'varchar', length: 255 }) + shortDescription: string; + + @Column({ type: 'varchar', length: 255 }) + eventType: string; + + @Column({ type: 'boolean', default: false }) + isRestricted: boolean; + + @Column({ type: 'varchar', length: 255, nullable: true }) + location: string; + + @Column({ type: 'double precision', nullable: true }) + longitude: number; + + @Column({ type: 'double precision', nullable: true }) + latitude: number; + + @Column({ type: 'varchar', length: 255, nullable: true }) + onlineProvider: string; + + @Column({ type: 'int', default: 0 }) + maxAttendees: number; + + @Column({ type: 'jsonb' }) + recordings: object; + + @Column({ type: 'varchar', length: 255 }) + status: string; + + @Column({ type: 'text' }) + description: string; + + @Column({ type: 'jsonb' }) + params: object; + + @CreateDateColumn({ + type: 'timestamptz', + default: () => 'CURRENT_TIMESTAMP', + transformer: new TimeZoneTransformer(new ConfigService()), + }) + createdAt: Date; + + @UpdateDateColumn({ + type: 'timestamptz', + default: () => 'CURRENT_TIMESTAMP', + transformer: new TimeZoneTransformer(new ConfigService()), + }) + updatedAt: Date; + + @Column({ type: 'jsonb', nullable: true }) + meetingDetails: object; + + @Column({ type: 'uuid', nullable: true }) + createdBy: string; + + @Column({ type: 'uuid', nullable: true }) + updatedBy: string; + + @Column({ type: 'int', nullable: true }) + idealTime: number; + + @Column({ type: 'jsonb', nullable: true }) + metadata: object; + + @OneToMany(() => Events, (event) => event.eventDetail) + events: Event[]; + + // @OneToMany( + // () => EventRepetition, + // (eventRepetition) => eventRepetition.eventDetail, + // ) + // eventRepetitions: EventRepetition[]; +} diff --git a/src/modules/event/entities/eventRepetition.entity.ts b/src/modules/event/entities/eventRepetition.entity.ts new file mode 100644 index 0000000..a16b50a --- /dev/null +++ b/src/modules/event/entities/eventRepetition.entity.ts @@ -0,0 +1,58 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, +} from 'typeorm'; +import { Events } from './event.entity'; +import { EventDetail } from './eventDetail.entity'; +import { TimeZoneTransformer } from '../../../common/utils/transformer/date.transformer'; +import { ConfigService } from '@nestjs/config'; + +@Entity('EventRepetition') +export class EventRepetition { + @PrimaryGeneratedColumn('uuid') + eventRepetitionId: string; + + @Column({ type: 'uuid', nullable: true }) + eventId: string; + + @Column({ type: 'uuid', nullable: true }) + eventDetailId: string; + + @Column({ type: 'jsonb', nullable: true }) + onlineDetails: object; + + @Column({ + type: 'timestamptz', + default: () => "timezone('utc', now())", + nullable: true, + transformer: new TimeZoneTransformer(new ConfigService()), + }) + startDateTime: Date; + + @Column({ + type: 'timestamptz', + default: () => "timezone('utc', now())", + nullable: true, + transformer: new TimeZoneTransformer(new ConfigService()), + }) + endDateTime: Date; + + // @ManyToOne(() => Events, (event) => event.eventRepetitions, { + // onDelete: 'CASCADE', + // onUpdate: 'CASCADE', + // }) + // @JoinColumn({ name: 'eventId' }) + // event: Event; + + // @ManyToOne(() => EventDetail, (eventDetail) => eventDetail.eventRepetitions, { + // onDelete: 'CASCADE', + // onUpdate: 'CASCADE', + // }) + // @JoinColumn({ name: 'eventDetailId' }) + // eventDetail: EventDetail; +}