@eventista/ticketing-common 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/README.md +2 -0
  2. package/dist/database/index.d.ts +2 -0
  3. package/dist/database/index.js +19 -0
  4. package/dist/database/index.js.map +1 -0
  5. package/dist/database/mongodb/index.d.ts +2 -0
  6. package/dist/database/mongodb/index.js +19 -0
  7. package/dist/database/mongodb/index.js.map +1 -0
  8. package/dist/database/mongodb/mongodb.module.d.ts +2 -0
  9. package/dist/database/mongodb/mongodb.module.js +50 -0
  10. package/dist/database/mongodb/mongodb.module.js.map +1 -0
  11. package/dist/database/mongodb/mongodb.service.d.ts +29 -0
  12. package/dist/database/mongodb/mongodb.service.js +114 -0
  13. package/dist/database/mongodb/mongodb.service.js.map +1 -0
  14. package/dist/database/redis/index.d.ts +2 -0
  15. package/dist/database/redis/index.js +19 -0
  16. package/dist/database/redis/index.js.map +1 -0
  17. package/dist/database/redis/redis.module.d.ts +2 -0
  18. package/dist/database/redis/redis.module.js +52 -0
  19. package/dist/database/redis/redis.module.js.map +1 -0
  20. package/dist/database/redis/redis.service.d.ts +26 -0
  21. package/dist/database/redis/redis.service.js +126 -0
  22. package/dist/database/redis/redis.service.js.map +1 -0
  23. package/dist/exception/exception.filter.d.ts +4 -0
  24. package/dist/exception/exception.filter.js +35 -0
  25. package/dist/exception/exception.filter.js.map +1 -0
  26. package/dist/generic-repository/index.d.ts +4 -0
  27. package/dist/generic-repository/index.js +21 -0
  28. package/dist/generic-repository/index.js.map +1 -0
  29. package/dist/generic-repository/repositories/base.repository.d.ts +39 -0
  30. package/dist/generic-repository/repositories/base.repository.interface.d.ts +36 -0
  31. package/dist/generic-repository/repositories/base.repository.interface.js +3 -0
  32. package/dist/generic-repository/repositories/base.repository.interface.js.map +1 -0
  33. package/dist/generic-repository/repositories/base.repository.js +96 -0
  34. package/dist/generic-repository/repositories/base.repository.js.map +1 -0
  35. package/dist/generic-repository/services/base.service.d.ts +42 -0
  36. package/dist/generic-repository/services/base.service.interface.d.ts +36 -0
  37. package/dist/generic-repository/services/base.service.interface.js +3 -0
  38. package/dist/generic-repository/services/base.service.interface.js.map +1 -0
  39. package/dist/generic-repository/services/base.service.js +57 -0
  40. package/dist/generic-repository/services/base.service.js.map +1 -0
  41. package/dist/index.d.ts +7 -0
  42. package/dist/index.js +24 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/logger/custom.logger.d.ts +14 -0
  45. package/dist/logger/custom.logger.js +76 -0
  46. package/dist/logger/custom.logger.js.map +1 -0
  47. package/dist/logger/index.d.ts +2 -0
  48. package/dist/logger/index.js +19 -0
  49. package/dist/logger/index.js.map +1 -0
  50. package/dist/logger/logger.module.d.ts +2 -0
  51. package/dist/logger/logger.module.js +27 -0
  52. package/dist/logger/logger.module.js.map +1 -0
  53. package/dist/pipes/custom-validation.pipe.d.ts +7 -0
  54. package/dist/pipes/custom-validation.pipe.js +69 -0
  55. package/dist/pipes/custom-validation.pipe.js.map +1 -0
  56. package/dist/response/response.interceptor.d.ts +5 -0
  57. package/dist/response/response.interceptor.js +29 -0
  58. package/dist/response/response.interceptor.js.map +1 -0
  59. package/dist/schemas/base.schema.d.ts +11 -0
  60. package/dist/schemas/base.schema.js +29 -0
  61. package/dist/schemas/base.schema.js.map +1 -0
  62. package/dist/schemas/event/event.interfaces.d.ts +69 -0
  63. package/dist/schemas/event/event.interfaces.js +9 -0
  64. package/dist/schemas/event/event.interfaces.js.map +1 -0
  65. package/dist/schemas/event/event.schema.d.ts +70 -0
  66. package/dist/schemas/event/event.schema.js +242 -0
  67. package/dist/schemas/event/event.schema.js.map +1 -0
  68. package/dist/schemas/index.d.ts +14 -0
  69. package/dist/schemas/index.js +31 -0
  70. package/dist/schemas/index.js.map +1 -0
  71. package/dist/schemas/order/order.interfaces.d.ts +72 -0
  72. package/dist/schemas/order/order.interfaces.js +31 -0
  73. package/dist/schemas/order/order.interfaces.js.map +1 -0
  74. package/dist/schemas/order/order.schema.d.ts +39 -0
  75. package/dist/schemas/order/order.schema.js +162 -0
  76. package/dist/schemas/order/order.schema.js.map +1 -0
  77. package/dist/schemas/promotions/promotions.interfaces.d.ts +30 -0
  78. package/dist/schemas/promotions/promotions.interfaces.js +14 -0
  79. package/dist/schemas/promotions/promotions.interfaces.js.map +1 -0
  80. package/dist/schemas/promotions/promotions.schema.d.ts +25 -0
  81. package/dist/schemas/promotions/promotions.schema.js +92 -0
  82. package/dist/schemas/promotions/promotions.schema.js.map +1 -0
  83. package/dist/schemas/rows/rows.interfaces.d.ts +14 -0
  84. package/dist/schemas/rows/rows.interfaces.js +3 -0
  85. package/dist/schemas/rows/rows.interfaces.js.map +1 -0
  86. package/dist/schemas/rows/rows.schema.d.ts +22 -0
  87. package/dist/schemas/rows/rows.schema.js +65 -0
  88. package/dist/schemas/rows/rows.schema.js.map +1 -0
  89. package/dist/schemas/schema.helper.d.ts +4 -0
  90. package/dist/schemas/schema.helper.js +84 -0
  91. package/dist/schemas/schema.helper.js.map +1 -0
  92. package/dist/schemas/ticket-classes/ticket-classes.interfaces.d.ts +18 -0
  93. package/dist/schemas/ticket-classes/ticket-classes.interfaces.js +3 -0
  94. package/dist/schemas/ticket-classes/ticket-classes.interfaces.js.map +1 -0
  95. package/dist/schemas/ticket-classes/ticket-classes.schemas.d.ts +26 -0
  96. package/dist/schemas/ticket-classes/ticket-classes.schemas.js +75 -0
  97. package/dist/schemas/ticket-classes/ticket-classes.schemas.js.map +1 -0
  98. package/dist/schemas/ticket-summary/ticket-summary.interfaces.d.ts +19 -0
  99. package/dist/schemas/ticket-summary/ticket-summary.interfaces.js +9 -0
  100. package/dist/schemas/ticket-summary/ticket-summary.interfaces.js.map +1 -0
  101. package/dist/schemas/ticket-summary/ticket-summary.schema.d.ts +23 -0
  102. package/dist/schemas/ticket-summary/ticket-summary.schema.js +65 -0
  103. package/dist/schemas/ticket-summary/ticket-summary.schema.js.map +1 -0
  104. package/dist/schemas/user-fanpass/user-fanpass.interfaces.d.ts +26 -0
  105. package/dist/schemas/user-fanpass/user-fanpass.interfaces.js +9 -0
  106. package/dist/schemas/user-fanpass/user-fanpass.interfaces.js.map +1 -0
  107. package/dist/schemas/user-fanpass/user-fanpass.schemas.d.ts +29 -0
  108. package/dist/schemas/user-fanpass/user-fanpass.schemas.js +113 -0
  109. package/dist/schemas/user-fanpass/user-fanpass.schemas.js.map +1 -0
  110. package/dist/tsconfig.tsbuildinfo +1 -0
  111. package/package.json +40 -0
  112. package/src/database/index.ts +2 -0
  113. package/src/database/mongodb/index.ts +2 -0
  114. package/src/database/mongodb/mongodb.module.ts +42 -0
  115. package/src/database/mongodb/mongodb.service.ts +111 -0
  116. package/src/database/redis/index.ts +2 -0
  117. package/src/database/redis/redis.module.ts +45 -0
  118. package/src/database/redis/redis.service.ts +142 -0
  119. package/src/exception/exception.filter.ts +36 -0
  120. package/src/generic-repository/index.ts +7 -0
  121. package/src/generic-repository/repositories/base.repository.interface.ts +78 -0
  122. package/src/generic-repository/repositories/base.repository.ts +199 -0
  123. package/src/generic-repository/services/base.service.interface.ts +78 -0
  124. package/src/generic-repository/services/base.service.ts +165 -0
  125. package/src/index.ts +11 -0
  126. package/src/logger/custom.logger.ts +83 -0
  127. package/src/logger/index.ts +2 -0
  128. package/src/logger/logger.module.ts +14 -0
  129. package/src/pipes/custom-validation.pipe.ts +61 -0
  130. package/src/response/response.interceptor.ts +26 -0
  131. package/src/schemas/base.schema.ts +19 -0
  132. package/src/schemas/event/event.interfaces.ts +74 -0
  133. package/src/schemas/event/event.schema.ts +195 -0
  134. package/src/schemas/index.ts +16 -0
  135. package/src/schemas/order/order.interfaces.ts +78 -0
  136. package/src/schemas/order/order.schema.ts +120 -0
  137. package/src/schemas/promotions/promotions.interfaces.ts +34 -0
  138. package/src/schemas/promotions/promotions.schema.ts +71 -0
  139. package/src/schemas/rows/rows.interfaces.ts +14 -0
  140. package/src/schemas/rows/rows.schema.ts +47 -0
  141. package/src/schemas/schema.helper.ts +103 -0
  142. package/src/schemas/ticket-classes/ticket-classes.interfaces.ts +18 -0
  143. package/src/schemas/ticket-classes/ticket-classes.schemas.ts +51 -0
  144. package/src/schemas/ticket-summary/ticket-summary.interfaces.ts +20 -0
  145. package/src/schemas/ticket-summary/ticket-summary.schema.ts +46 -0
  146. package/src/schemas/user-fanpass/user-fanpass.interfaces.ts +28 -0
  147. package/src/schemas/user-fanpass/user-fanpass.schemas.ts +86 -0
  148. package/tsconfig.json +17 -0
@@ -0,0 +1,165 @@
1
+ import { Document, FilterQuery, UpdateQuery, QueryOptions, PipelineStage } from 'mongoose';
2
+ import { IBaseRepository } from '../repositories/base.repository.interface';
3
+ import { Logger } from '@nestjs/common';
4
+ import { IBaseService } from './base.service.interface';
5
+
6
+ export class BaseService<T extends Document> implements IBaseService<T> {
7
+ protected readonly logger: Logger;
8
+
9
+ constructor(
10
+ protected readonly repository: IBaseRepository<T>,
11
+ context?: string,
12
+ ) {
13
+ this.logger = new Logger(context || this.constructor.name);
14
+ }
15
+
16
+ /**
17
+ * Tìm một document theo điều kiện
18
+ */
19
+ async findOne(
20
+ filterQuery: FilterQuery<T>,
21
+ projection?: Record<string, unknown>,
22
+ options?: QueryOptions,
23
+ ): Promise<T | null> {
24
+ return this.repository.findOne(filterQuery, projection, options);
25
+ }
26
+
27
+ /**
28
+ * Tìm một document theo điều kiện hoặc throw exception nếu không tìm thấy
29
+ */
30
+ async findOneOrFail(
31
+ filterQuery: FilterQuery<T>,
32
+ projection?: Record<string, unknown>,
33
+ options?: QueryOptions,
34
+ ): Promise<T> {
35
+ return this.repository.findOneOrFail(filterQuery, projection, options);
36
+ }
37
+
38
+ /**
39
+ * Tìm nhiều documents theo điều kiện
40
+ */
41
+ async find(
42
+ filterQuery: FilterQuery<T>,
43
+ projection?: Record<string, unknown>,
44
+ options?: QueryOptions,
45
+ ): Promise<T[]> {
46
+ return this.repository.find(filterQuery, projection, options);
47
+ }
48
+
49
+ /**
50
+ * Tạo một document mới
51
+ */
52
+ async create(createDto: Partial<T>): Promise<T> {
53
+ return this.repository.create(createDto);
54
+ }
55
+
56
+ /**
57
+ * Tạo nhiều documents
58
+ */
59
+ async createMany(createDtos: Partial<T>[]): Promise<T[]> {
60
+ return this.repository.createMany(createDtos);
61
+ }
62
+
63
+ /**
64
+ * Cập nhật một document theo điều kiện
65
+ */
66
+ async update(
67
+ filterQuery: FilterQuery<T>,
68
+ updateQuery: UpdateQuery<T>,
69
+ options: QueryOptions = { new: true },
70
+ ): Promise<T | null> {
71
+ return this.repository.findOneAndUpdate(filterQuery, updateQuery, options);
72
+ }
73
+
74
+ /**
75
+ * Cập nhật một document theo điều kiện hoặc throw exception nếu không tìm thấy
76
+ */
77
+ async updateOrFail(
78
+ filterQuery: FilterQuery<T>,
79
+ updateQuery: UpdateQuery<T>,
80
+ options: QueryOptions = { new: true },
81
+ ): Promise<T> {
82
+ return this.repository.findOneAndUpdateOrFail(filterQuery, updateQuery, options);
83
+ }
84
+
85
+ /**
86
+ * Cập nhật nhiều documents theo điều kiện
87
+ */
88
+ async updateMany(
89
+ filterQuery: FilterQuery<T>,
90
+ updateQuery: UpdateQuery<T>,
91
+ ): Promise<{ matchedCount: number; modifiedCount: number }> {
92
+ return this.repository.updateMany(filterQuery, updateQuery);
93
+ }
94
+
95
+ /**
96
+ * Xóa một document theo điều kiện
97
+ */
98
+ async delete(
99
+ filterQuery: FilterQuery<T>,
100
+ options?: QueryOptions,
101
+ ): Promise<T | null> {
102
+ return this.repository.findOneAndDelete(filterQuery, options);
103
+ }
104
+
105
+ /**
106
+ * Xóa một document theo điều kiện hoặc throw exception nếu không tìm thấy
107
+ */
108
+ async deleteOrFail(
109
+ filterQuery: FilterQuery<T>,
110
+ options?: QueryOptions,
111
+ ): Promise<T> {
112
+ return this.repository.findOneAndDeleteOrFail(filterQuery, options);
113
+ }
114
+
115
+ /**
116
+ * Xóa nhiều documents theo điều kiện
117
+ */
118
+ async deleteMany(filterQuery: FilterQuery<T>): Promise<{ deletedCount: number }> {
119
+ return this.repository.deleteMany(filterQuery);
120
+ }
121
+
122
+ /**
123
+ * Đếm số lượng documents theo điều kiện
124
+ */
125
+ async count(filterQuery: FilterQuery<T>): Promise<number> {
126
+ return this.repository.count(filterQuery);
127
+ }
128
+
129
+ /**
130
+ * Kiểm tra document có tồn tại không
131
+ */
132
+ async exists(filterQuery: FilterQuery<T>): Promise<boolean> {
133
+ return this.repository.exists(filterQuery);
134
+ }
135
+
136
+ /**
137
+ * Thực hiện aggregation pipeline
138
+ */
139
+ async aggregate(pipeline: PipelineStage[]): Promise<any[]> {
140
+ return this.repository.aggregate(pipeline);
141
+ }
142
+
143
+ /**
144
+ * Phân trang
145
+ */
146
+ async paginate(
147
+ filterQuery: FilterQuery<T>,
148
+ options: {
149
+ page?: number;
150
+ limit?: number;
151
+ sort?: Record<string, 1 | -1>;
152
+ projection?: Record<string, unknown>;
153
+ } = {},
154
+ ): Promise<{
155
+ data: T[];
156
+ pagination: {
157
+ total: number;
158
+ page: number;
159
+ limit: number;
160
+ pages: number;
161
+ };
162
+ }> {
163
+ return this.repository.paginate(filterQuery, options);
164
+ }
165
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+
2
+ export * from './database';
3
+ export * from './exception/exception.filter';
4
+ export * from './generic-repository';
5
+
6
+ export * from './logger';
7
+
8
+ export * from './pipes/custom-validation.pipe';
9
+ export * from './response/response.interceptor'
10
+
11
+ export * from './schemas';
@@ -0,0 +1,83 @@
1
+ import { LoggerService } from '@nestjs/common';
2
+ import { blue, cyan, gray, green, red, yellow } from 'colorette';
3
+
4
+ export class CustomLogger implements LoggerService {
5
+ private readonly isProduction: boolean;
6
+
7
+ constructor(private readonly context?: string) {
8
+ this.isProduction = process.env.NODE_ENV === 'production';
9
+ }
10
+
11
+
12
+ private getTimestamp(): string {
13
+ const localeStringOptions = {
14
+ year: 'numeric',
15
+ hour: 'numeric',
16
+ minute: 'numeric',
17
+ second: 'numeric',
18
+ day: '2-digit',
19
+ month: '2-digit',
20
+ };
21
+ return new Date().toLocaleString(undefined, localeStringOptions as Intl.DateTimeFormatOptions);
22
+ }
23
+
24
+ private formatMessage(level: string, message: string, context?: string): string {
25
+ if (this.isProduction) {
26
+ return JSON.stringify({
27
+ timestamp: this.getTimestamp(),
28
+ pid: process.pid,
29
+ level,
30
+ context: context || this.context,
31
+ message
32
+ });
33
+ }
34
+
35
+ const timestamp = gray(`[Nest] ${process.pid} - ${this.getTimestamp()}`);
36
+ const formattedLevel = this.colorize(level);
37
+ const contextStr = yellow(`[${context || this.context}] `);
38
+ return `${timestamp} ${formattedLevel} ${contextStr}${message}`;
39
+ }
40
+
41
+ private colorize(level: string): string {
42
+ switch (level) {
43
+ case 'LOG':
44
+ return green(`${level} `);
45
+ case 'ERROR':
46
+ return red(`${level}`);
47
+ case 'WARN':
48
+ return yellow(`${level} `);
49
+ case 'DEBUG':
50
+ return blue(`${level}`);
51
+ case 'VERBOSE':
52
+ return cyan(`${level}`);
53
+ default:
54
+ return level;
55
+ }
56
+ }
57
+
58
+ log(message: string, context?: string) {
59
+ console.log(this.formatMessage('LOG', message, context));
60
+ }
61
+
62
+ error(message: string, metadata?: any) {
63
+ const baseLog = this.formatMessage('ERROR', message);
64
+ if (metadata) {
65
+ console.error(baseLog);
66
+ console.error(red('Details:'), metadata);
67
+ } else {
68
+ console.error(baseLog);
69
+ }
70
+ }
71
+
72
+ warn(message: string, context?: string) {
73
+ console.warn(this.formatMessage('WARN', message, context));
74
+ }
75
+
76
+ debug(message: string, context?: string) {
77
+ console.debug(this.formatMessage('DEBUG', message, context));
78
+ }
79
+
80
+ verbose(message: string, context?: string) {
81
+ console.log(this.formatMessage('VERBOSE', message, context));
82
+ }
83
+ }
@@ -0,0 +1,2 @@
1
+ export * from './logger.module';
2
+ export * from './custom.logger';
@@ -0,0 +1,14 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { CustomLogger } from './custom.logger';
3
+
4
+ @Global()
5
+ @Module({
6
+ providers: [
7
+ {
8
+ provide: 'Logger',
9
+ useValue: new CustomLogger(), // Initialize with no context
10
+ },
11
+ ],
12
+ exports: ['Logger'],
13
+ })
14
+ export class LoggerModule {}
@@ -0,0 +1,61 @@
1
+ import {
2
+ ArgumentMetadata,
3
+ BadRequestException,
4
+ Injectable,
5
+ ValidationPipe,
6
+ ValidationPipeOptions,
7
+ } from '@nestjs/common';
8
+
9
+ @Injectable()
10
+ export class CustomValidationPipe extends ValidationPipe {
11
+ constructor(options?: ValidationPipeOptions) {
12
+ super({
13
+ whitelist: true, // Loại bỏ các trường không có trong DTO
14
+ transform: true, // Tự động chuyển đổi dữ liệu đầu vào thành class instance của DTO
15
+ ...options, // Cho phép truyền thêm tùy chọn nếu cần
16
+ });
17
+ }
18
+ public async transform(value, metadata: ArgumentMetadata) {
19
+ try {
20
+ return await super.transform(value, metadata);
21
+ } catch (e) {
22
+ if (e instanceof BadRequestException) {
23
+ const errors: any = [];
24
+ for (const err of e.getResponse()['message']) {
25
+ errors.push({
26
+ field: err.property,
27
+ constraints: this.getConstraints(err),
28
+ });
29
+ }
30
+
31
+ throw new BadRequestException({
32
+ errorCode: 400,
33
+ message: 'Validation failed',
34
+ errors,
35
+ });
36
+ }
37
+ }
38
+ }
39
+
40
+ getConstraints(err) {
41
+ if (typeof err == 'string') {
42
+ return err;
43
+ }
44
+ if (typeof err == 'object' && err.constraints) {
45
+ return err.constraints;
46
+ }
47
+ return this.deepReduce(err.children);
48
+ }
49
+
50
+ deepReduce(array) {
51
+ return array.reduce((accumulator, currentValue) => {
52
+ if (currentValue.children && currentValue.children.length > 0) {
53
+ return this.deepReduce(currentValue.children);
54
+ }
55
+ if (currentValue.constraints) {
56
+ return currentValue.constraints;
57
+ }
58
+ return accumulator;
59
+ }, {});
60
+ }
61
+ }
@@ -0,0 +1,26 @@
1
+ import {
2
+ CallHandler,
3
+ ExecutionContext,
4
+ Injectable,
5
+ NestInterceptor,
6
+ } from '@nestjs/common';
7
+ import { Observable } from 'rxjs';
8
+ import { map } from 'rxjs/operators';
9
+
10
+ @Injectable()
11
+ export class ResponseInterceptor implements NestInterceptor {
12
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
13
+ // Chỉ áp dụng cho HTTP hoặc HTTPS requests
14
+ if (context.getType() !== 'http') {
15
+ return next.handle();
16
+ }
17
+ return next.handle().pipe(
18
+ map((data) => ({
19
+ errorCode: 0,
20
+ message: 'Success',
21
+ data,
22
+ timestamp: new Date().toISOString(),
23
+ })),
24
+ );
25
+ }
26
+ }
@@ -0,0 +1,19 @@
1
+ import { Prop, Schema } from '@nestjs/mongoose';
2
+ import { Document } from 'mongoose';
3
+
4
+ export interface BaseDocument extends Document {
5
+ createdAt: Date;
6
+ updatedAt: Date;
7
+ isDeleted: boolean;
8
+ }
9
+
10
+ export class BaseSchema {
11
+ @Prop({ type: Date, default: Date.now })
12
+ createdAt: Date;
13
+
14
+ @Prop({ type: Date, default: Date.now })
15
+ updatedAt: Date;
16
+
17
+ @Prop({ type: Boolean, default: false })
18
+ isDeleted: boolean;
19
+ }
@@ -0,0 +1,74 @@
1
+
2
+ export enum IStatusEvent {
3
+ OPEN = 'OPEN',
4
+ CLOSE = 'CLOSE',
5
+ }
6
+
7
+ export interface IPaymentInfoField {
8
+ key: string;
9
+ text: string;
10
+ type?: string;
11
+ isDefault?: boolean;
12
+ isRequired?: boolean;
13
+ }
14
+
15
+ export interface IGeneral {
16
+ collaboration?: 'eventista' | 'agency' | 'seatmap' | 'seatmap_zone';
17
+ ticketType?: 'e_ticket' | 'hard_ticket';
18
+ paymentInfoFields?: IPaymentInfoField[];
19
+ }
20
+
21
+ export interface IVisitor {
22
+ name?: string;
23
+ picture?: string;
24
+ id?: string;
25
+ }
26
+
27
+ export type Category = 'concert' | 'live_show' | 'workshop' | 'fan_meeting';
28
+
29
+ export interface IEventCalendar {
30
+ calendarId: string;
31
+ startDate: Date;
32
+ endDate: Date;
33
+ maxTicketPerUser?: number;
34
+ }
35
+
36
+ export interface ITicketCalendar {
37
+ thumbnail?: string;
38
+ description?: string;
39
+ }
40
+
41
+ export interface IEvent {
42
+ _id?: string;
43
+ eventName: string;
44
+ location: string;
45
+ address: string;
46
+ pathName: string;
47
+ thumbnail?: string;
48
+ logo?: string;
49
+ venueMap?: string;
50
+ status?: IStatusEvent;
51
+ eventCalendar: IEventCalendar[];
52
+ ticketCalendar?: ITicketCalendar;
53
+ hostedBy?: string;
54
+ tickets: Record<string, any>[];
55
+ eventDescriptions?: { title: string; description: string }[];
56
+ maxTicketPerUser: number;
57
+ note: string;
58
+ general?: IGeneral;
59
+ domain: string;
60
+ categories?: Category[];
61
+ featuredFlg?: boolean;
62
+ hideInMarketPlace?: boolean;
63
+ tenantId?: string;
64
+ visitors?: IVisitor[];
65
+ background?: string;
66
+ headingBackground?: string;
67
+ fanpassId?: string;
68
+ discountForFanpassUser?: boolean;
69
+ type?: string;
70
+ authRequired?: boolean;
71
+ createdAt?: Date;
72
+ updatedAt?: Date;
73
+ isDeleted?: boolean;
74
+ }
@@ -0,0 +1,195 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import { HydratedDocument } from 'mongoose';
3
+ import { BaseDocument, BaseSchema, addSoftDeleteHooks, addUpdateHooks, defaultSchemaOptions } from '../index';
4
+ import { IStatusEvent } from './event.interfaces';
5
+
6
+ export type EventDocument = HydratedDocument<Event> & BaseDocument;
7
+
8
+
9
+ @Schema({ _id: false })
10
+ export class SchemaPaymentInfoField {
11
+ @Prop({ required: true })
12
+ key: string;
13
+
14
+ @Prop({ required: true })
15
+ text: string;
16
+
17
+ @Prop({ default: 'text' })
18
+ type: string;
19
+
20
+ @Prop({ default: false })
21
+ isDefault: boolean;
22
+
23
+ @Prop({ default: false })
24
+ isRequired: boolean;
25
+ }
26
+
27
+ @Schema({ _id: false })
28
+ export class SchemaGeneral {
29
+ @Prop({ enum: ['eventista', 'agency', 'seatmap', 'seatmap_zone'], default: 'eventista' })
30
+ collaboration: string;
31
+
32
+ @Prop({ enum: ['e_ticket', 'hard_ticket'], default: 'hard_ticket' })
33
+ ticketType: string;
34
+
35
+ @Prop({ type: [SchemaPaymentInfoField], default: [] })
36
+ paymentInfoFields: SchemaPaymentInfoField[];
37
+ }
38
+
39
+ @Schema({ _id: false }) // Nếu bạn không cần _id riêng cho mỗi visitor
40
+ export class SchemaVisitor {
41
+ @Prop() name: string;
42
+ @Prop() picture: string;
43
+ @Prop() id: string;
44
+ }
45
+
46
+
47
+ @Schema({
48
+ collection: 'events',
49
+ ...defaultSchemaOptions,
50
+ })
51
+ export class Event extends BaseSchema {
52
+ @Prop({ required: true })
53
+ eventName: string;
54
+
55
+ @Prop({ required: true })
56
+ location: String;
57
+
58
+ @Prop({ required: true })
59
+ address: string;
60
+
61
+ @Prop({ required: true })
62
+ pathName: string;
63
+
64
+ @Prop({ required: false })
65
+ thumbnail: string;
66
+
67
+ @Prop({ required: false })
68
+ logo: string;
69
+
70
+ @Prop({ required: false })
71
+ venueMap: string;
72
+
73
+ @Prop({ enum: Object.values(IStatusEvent), default: "OPEN" })
74
+ status: string;
75
+
76
+ @Prop({
77
+ type: [
78
+ {
79
+ calendarId: { type: String, required: true },
80
+ startDate: { type: Date, required: true },
81
+ endDate: { type: Date, required: true },
82
+ maxTicketPerUser: { type: Number, default: -1 },
83
+ },
84
+ ],
85
+ required: true,
86
+ default: [],
87
+ })
88
+ eventCalendar: {
89
+ calendarId: String;
90
+ startDate: Date;
91
+ endDate: Date;
92
+ maxTicketPerUser: number;
93
+ }[];
94
+
95
+ @Prop({
96
+ type: {
97
+ thumbnail: { type: String, required: false },
98
+ description: { type: String, required: false },
99
+ },
100
+ required: false,
101
+ default: {},
102
+ })
103
+ ticketCalendar: {
104
+ thumbnail: String;
105
+ description: String;
106
+ };
107
+
108
+ @Prop({})
109
+ hostedBy: String
110
+
111
+ // check lại nếu bị lỗi khi tạo event
112
+ @Prop({ type: [Object], required: true, default: [] }) // Mảng các object không xác định cấu trúc
113
+ tickets: Record<string, any>[];
114
+
115
+ @Prop({
116
+ type: [
117
+ {
118
+ title: { type: String },
119
+ description: { type: String },
120
+ },
121
+ ],
122
+ required: false,
123
+ default: []
124
+ })
125
+ eventDescriptions: { title: string; description: string }[];
126
+
127
+ @Prop({
128
+ type: Number,
129
+ required: true,
130
+ default: 0,
131
+ })
132
+ maxTicketPerUser: number;
133
+
134
+ @Prop({ type: String, required: true })
135
+ note: string;
136
+
137
+ @Prop({ type: SchemaGeneral, default: {} })
138
+ general: SchemaGeneral;
139
+
140
+ @Prop({ type: String, required: true })
141
+ domain: string;
142
+
143
+ @Prop({
144
+ type: [String],
145
+ enum: ['concert', 'live_show', 'workshop', 'fan_meeting'],
146
+ default: [],
147
+ })
148
+ categories: ('concert' | 'live_show' | 'workshop' | 'fan_meeting')[];
149
+
150
+ @Prop({ type: Boolean, default: false })
151
+ featuredFlg: boolean;
152
+
153
+ @Prop({ type: Boolean, default: false })
154
+ hideInMarketPlace: boolean;
155
+
156
+ @Prop({ type: String, required: false })
157
+ tenantId: string;
158
+
159
+ @Prop({ type: [SchemaVisitor], default: [] })
160
+ visitors: SchemaVisitor[];
161
+
162
+ @Prop({ type: String, required: false })
163
+ background: string;
164
+
165
+ @Prop({ type: String, required: false })
166
+ headingBackground: string;
167
+
168
+ @Prop({ type: String, required: false })
169
+ fanpassId: string;
170
+
171
+ @Prop({ type: Boolean, default: false })
172
+ discountForFanpassUser: boolean;
173
+
174
+ @Prop({ type: String, required: false })
175
+ type: string;
176
+
177
+ @Prop({ type: Boolean, default: false })
178
+ authRequired: boolean;
179
+ }
180
+
181
+
182
+
183
+ export const EventSchema = SchemaFactory.createForClass(Event);
184
+
185
+ // Thêm các hooks và middleware
186
+ addSoftDeleteHooks(EventSchema);
187
+ addUpdateHooks(EventSchema);
188
+
189
+ //Thêm các index
190
+ EventSchema.index({ isDeleted: 1 });
191
+ EventSchema.index({ eventName: 1 });
192
+ EventSchema.index({ pathName: 1 });
193
+ EventSchema.index({ status: 1 });
194
+ EventSchema.index({ tenantId: 1 });
195
+
@@ -0,0 +1,16 @@
1
+ export * from './base.schema';
2
+ export * from './schema.helper';
3
+ export * from './ticket-summary/ticket-summary.interfaces';
4
+ export * from './ticket-summary/ticket-summary.schema';
5
+ export * from './ticket-classes/ticket-classes.interfaces';
6
+ export * from './ticket-classes/ticket-classes.schemas';
7
+ export * from './rows/rows.interfaces';
8
+ export * from './rows/rows.schema';
9
+ export * from './order/order.interfaces';
10
+ export * from './order/order.schema';
11
+ export * from './event/event.interfaces';
12
+ export * from './event/event.schema';
13
+ export * from './user-fanpass/user-fanpass.interfaces';
14
+ export * from './user-fanpass/user-fanpass.schemas';
15
+
16
+