push code ne

This commit is contained in:
2024-10-28 01:08:13 +07:00
parent 571bb93e28
commit eec9fcfeff
20 changed files with 296 additions and 118 deletions

View File

@@ -0,0 +1,8 @@
import { AdminNoteSchema } from './adminnote.schema';
import { Module } from '@nestjs/common';
@Module({
providers: [AdminNoteSchema],
exports: [AdminNoteSchema],
})
export class AdminNoteModule {}

View File

@@ -0,0 +1,89 @@
import { Inject, Injectable } from '@nestjs/common';
import {
Pothos,
PothosRef,
PothosSchema,
SchemaBuilderToken,
} from '@smatch-corp/nestjs-pothos';
import { Builder } from '../Graphql/graphql.builder';
import { PrismaService } from '../Prisma/prisma.service';
@Injectable()
export class AdminNoteSchema extends PothosSchema {
constructor(
@Inject(SchemaBuilderToken) private readonly builder: Builder,
private readonly prisma: PrismaService,
) {
super();
}
@PothosRef()
adminNote() {
return this.builder.prismaObject('AdminNote', {
description: 'An admin note.',
fields: (t) => ({
id: t.exposeID('id', {
description: 'The ID of the admin note.',
}),
content: t.exposeString('content', {
description: 'The content of the admin note.',
}),
notedByUserId: t.exposeString('notedByUserId', {
description: 'The ID of the user who created the admin note.',
}),
notedBy: t.relation('notedBy', {
description: 'The user who created the admin note.',
}),
createdAt: t.expose('createdAt', {
type: 'DateTime',
description: 'The date and time the admin note was created.',
}),
updatedAt: t.expose('updatedAt', {
type: 'DateTime',
description: 'The date and time the admin note was last updated.',
}),
center: t.relation('center', {
description: 'The center the admin note is associated with.',
}),
service: t.relation('service', {
description: 'The service the admin note is associated with.',
}),
serviceId: t.exposeString('serviceId', {
description:
'The ID of the service the admin note is associated with.',
}),
}),
});
}
@Pothos()
init(): void {
this.builder.queryFields((t) => ({
adminNote: t.prismaField({
type: this.adminNote(),
args: this.builder.generator.findUniqueArgs('AdminNote'),
description: 'Retrieve a single admin note by its unique identifier.',
resolve: async (query, root, args, ctx, info) => {
return await this.prisma.adminNote.findUnique({
...query,
where: args.where,
});
},
}),
adminNotes: t.prismaField({
type: [this.adminNote()],
args: this.builder.generator.findManyArgs('AdminNote'),
description: 'Retrieve a list of admin notes.',
resolve: async (query, root, args, ctx, info) => {
return await this.prisma.adminNote.findMany({
...query,
where: args.filter ?? undefined,
orderBy: args.orderBy ?? undefined,
skip: args.skip ?? undefined,
take: args.take ?? undefined,
});
},
}),
}));
}
}

View File

View File

View File

View File

@@ -44,6 +44,9 @@ export class CenterSchema extends PothosSchema {
description: t.exposeString('description', {
description: 'The description of the center.',
}),
adminNote: t.relation('adminNote', {
description: 'The admin note of the center.',
}),
logoUrl: t.exposeString('logoUrl', {
description: 'The URL of the center logo.',
}),
@@ -68,8 +71,8 @@ export class CenterSchema extends PothosSchema {
chatRoom: t.relation('chatRoom', {
description: 'The chat room associated with the center.',
}),
centerStaff: t.relation('centerStaff', {
description: 'The staff members of the center.',
centerMentor: t.relation('centerMentors', {
description: 'The mentors of the center.',
}),
resume: t.relation('resume', {
description: 'The resume of the center.',
@@ -114,8 +117,8 @@ export class CenterSchema extends PothosSchema {
});
},
}),
// get current center of centerstaff by providing userId
centerByCenterStaff: t.prismaField({
// get current center of centermentor by providing userId
centerByCenterMentor: t.prismaField({
type: this.center(),
description: 'Retrieve a single center by its unique identifier.',
args: {
@@ -124,9 +127,9 @@ export class CenterSchema extends PothosSchema {
resolve: async (query, root, args, ctx, info) => {
return await this.prisma.center.findFirst({
where: {
centerStaff: {
centerMentors: {
some: {
staffId: args.userId,
mentorId: args.userId,
},
},
},
@@ -192,7 +195,7 @@ export class CenterSchema extends PothosSchema {
}),
approveOrRejectCenter: t.prismaField({
type: this.center(),
description: 'Approve a center and promote centerstaff to staff',
description: 'Approve a center and promote centermentor to mentor',
args: {
centerId: t.arg({
type: 'String',
@@ -218,10 +221,10 @@ export class CenterSchema extends PothosSchema {
if (center.centerStatus !== CenterStatus.PENDING) {
throw new Error('Center is already approved or rejected');
}
// find center owner and promote to staff
// find user and promote to center owner
const centerOwnerId = center.centerOwnerId;
if (!centerOwnerId) {
throw new Error('Center owner not found');
throw new Error('User not found');
}
const centerOwner = await prisma.user.findUnique({
where: {
@@ -229,7 +232,7 @@ export class CenterSchema extends PothosSchema {
},
});
if (!centerOwner) {
throw new Error('Center owner not found');
throw new Error('User not found');
}
await prisma.user.update({
where: {

View File

@@ -0,0 +1,8 @@
import { CenterMentorSchema } from './centermentor.schema';
import { Module } from '@nestjs/common';
@Module({
providers: [CenterMentorSchema],
exports: [CenterMentorSchema],
})
export class CenterMentorModule {}

View File

@@ -10,7 +10,7 @@ import { PrismaService } from '../Prisma/prisma.service';
import { MailService } from '../Mail/mail.service';
import { JwtUtils } from '../common/utils/jwt.utils';
@Injectable()
export class CenterStaffSchema extends PothosSchema {
export class CenterMentorSchema extends PothosSchema {
constructor(
@Inject(SchemaBuilderToken) private readonly builder: Builder,
private readonly prisma: PrismaService,
@@ -21,27 +21,30 @@ export class CenterStaffSchema extends PothosSchema {
}
@PothosRef()
centerStaff() {
return this.builder.prismaObject('CenterStaff', {
description: 'A staff member of a center.',
centerMentor() {
return this.builder.prismaObject('CenterMentor', {
description: 'A mentor of a center.',
fields: (t) => ({
staffId: t.exposeID('staffId', {
description: 'The ID of the staff member.',
mentorId: t.exposeID('mentorId', {
description: 'The ID of the mentor.',
}),
centerId: t.exposeID('centerId', {
description: 'The ID of the center.',
}),
staff: t.relation('staff', {
description: 'The staff member.',
isCenterOwner: t.exposeBoolean('isCenterOwner', {
description: 'Whether the mentor is the center owner.',
}),
mentor: t.relation('mentor', {
description: 'The mentor.',
}),
center: t.relation('center', {
description: 'The center.',
}),
createdWorkshop: t.relation('createdWorkshop', {
description: 'The workshops created by the center staff.',
description: 'The workshops created by the center mentor.',
}),
managedService: t.relation('managedService', {
description: 'The managed services of the center staff.',
description: 'The managed services of the center mentor.',
}),
}),
});
@@ -50,13 +53,13 @@ export class CenterStaffSchema extends PothosSchema {
@Pothos()
init(): void {
this.builder.queryFields((t) => ({
centerStaff: t.prismaField({
centerMentor: t.prismaField({
description:
'Retrieve a list of center staff members with optional filtering, ordering, and pagination.',
type: [this.centerStaff()],
args: this.builder.generator.findManyArgs('CenterStaff'),
'Retrieve a list of center mentors with optional filtering, ordering, and pagination.',
type: [this.centerMentor()],
args: this.builder.generator.findManyArgs('CenterMentor'),
resolve: async (query, root, args) => {
return await this.prisma.centerStaff.findMany({
return await this.prisma.centerMentor.findMany({
...query,
skip: args.skip ?? undefined,
take: args.take ?? 10,
@@ -69,38 +72,38 @@ export class CenterStaffSchema extends PothosSchema {
// mutations
this.builder.mutationFields((t) => ({
createCenterStaff: t.prismaField({
type: this.centerStaff(),
description: 'Create a new center staff member.',
createCenterMentor: t.prismaField({
type: this.centerMentor(),
description: 'Create a new center mentor.',
args: {
data: t.arg({
type: this.builder.generator.getCreateInput('CenterStaff'),
type: this.builder.generator.getCreateInput('CenterMentor'),
required: true,
}),
},
resolve: async (query, root, args) => {
return await this.prisma.centerStaff.create({
return await this.prisma.centerMentor.create({
...query,
data: args.data,
});
},
}),
updateCenterStaff: t.prismaField({
type: this.centerStaff(),
description: 'Update an existing center staff member.',
updateCenterMentor: t.prismaField({
type: this.centerMentor(),
description: 'Update an existing center mentor.',
args: {
where: t.arg({
type: this.builder.generator.getWhereUnique('CenterStaff'),
type: this.builder.generator.getWhereUnique('CenterMentor'),
required: true,
}),
data: t.arg({
type: this.builder.generator.getUpdateInput('CenterStaff'),
type: this.builder.generator.getUpdateInput('CenterMentor'),
required: true,
}),
},
resolve: async (query, root, args) => {
return await this.prisma.centerStaff.update({
return await this.prisma.centerMentor.update({
...query,
where: args.where,
data: args.data,
@@ -108,25 +111,25 @@ export class CenterStaffSchema extends PothosSchema {
},
}),
deleteCenterStaff: t.prismaField({
type: this.centerStaff(),
description: 'Delete an existing center staff member.',
deleteCenterMentor: t.prismaField({
type: this.centerMentor(),
description: 'Delete an existing center mentor.',
args: {
where: t.arg({
type: this.builder.generator.getWhereUnique('CenterStaff'),
type: this.builder.generator.getWhereUnique('CenterMentor'),
required: true,
}),
},
resolve: async (query, root, args) => {
return await this.prisma.centerStaff.delete({
return await this.prisma.centerMentor.delete({
...query,
where: args.where,
});
},
}),
inviteCenterStaff: t.prismaField({
type: this.centerStaff(),
description: 'Invite a new center staff member.',
inviteCenterMentor: t.prismaField({
type: this.centerMentor(),
description: 'Invite a new center mentor.',
args: {
email: t.arg({ type: 'String', required: true }),
},
@@ -155,7 +158,7 @@ export class CenterStaffSchema extends PothosSchema {
await this.mailService.sendTemplateEmail(
args.email,
'Invite to center',
'StaffInvitation',
'MentorInvitation',
{
center_name: center.name,
invite_url: inviteUrl,

View File

@@ -1,8 +0,0 @@
import { Module } from '@nestjs/common';
import { CenterStaffSchema } from './centerstaff.schema';
@Module({
providers: [CenterStaffSchema],
exports: [CenterStaffSchema],
})
export class CenterStaffModule {}

View File

@@ -36,8 +36,8 @@ export class ChatroomSchema extends PothosSchema {
centerId: t.exposeID('centerId', {
description: 'The ID of the center.',
}),
centerStaffId: t.exposeID('centerStaffId', {
description: 'The ID of the center staff member.',
mentorId: t.exposeID('mentorId', {
description: 'The ID of the mentor.',
}),
createdAt: t.expose('createdAt', {
type: 'DateTime',
@@ -52,8 +52,8 @@ export class ChatroomSchema extends PothosSchema {
center: t.relation('center', {
description: 'The center.',
}),
centerStaff: t.relation('centerStaff', {
description: 'The center staff member.',
mentor: t.relation('mentor', {
description: 'The mentor.',
}),
meetingRoom: t.relation('meetingRoom', {
description: 'The meeting room.',

View File

@@ -55,6 +55,10 @@ export interface SchemaBuilderOption {
Input: FileUpload;
Output: FileUpload;
};
Int: {
Input: number;
Output: number | bigint | string;
};
};
}

View File

@@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import { Int } from '@nestjs/graphql';
import {
type BaseEnum,
@@ -33,7 +34,6 @@ const scalarListOps = [
] as const;
const JsonFilterOps = ['equals', 'in', 'notIn', 'not'] as const;
const EnumFilterOps = ['equals', 'not'] as const;
@Injectable()
export class PrismaCrudGenerator<Types extends SchemaTypes> {
private refCache = new Map<
@@ -67,6 +67,8 @@ export class PrismaCrudGenerator<Types extends SchemaTypes> {
take: t.field({
type: 'Int',
required: false,
// @ts-expect-error: Int is not a valid default value
defaultValue: 10,
}),
skip: t.field({
type: 'Int',

View File

@@ -1,10 +1,11 @@
import { Global, Logger, MiddlewareConsumer, Module } from '@nestjs/common';
import { AdminNoteModule } from '../AdminNote/adminnote.module';
import { ApolloDriverConfig } from '@nestjs/apollo';
import { Builder } from './graphql.builder';
import { CategoryModule } from '../Category/category.module';
import { CenterMentorModule } from '../CenterMentor/centermentor.module';
import { CenterModule } from '../Center/center.module';
import { CenterStaffModule } from '../CenterStaff/centerstaff.module';
import { ChatroomModule } from '../ChatRoom/chatroom.module';
import { CommonModule } from '../common/common.module';
import { GraphQLModule } from '@nestjs/graphql';
@@ -45,7 +46,7 @@ import { initContextCache } from '@pothos/core';
CenterModule,
ServiceModule,
ChatroomModule,
CenterStaffModule,
CenterMentorModule,
ResumeModule,
WorkshopModule,
WorkshopOrganizationModule,
@@ -63,6 +64,7 @@ import { initContextCache } from '@pothos/core';
UploadedFileModule,
ManagedServiceModule,
WorkshopMeetingRoomModule,
AdminNoteModule,
PothosModule.forRoot({
builder: {
inject: [PrismaService],

View File

@@ -25,14 +25,17 @@ export class ManagedServiceSchema extends PothosSchema {
id: t.exposeID('id', {
description: 'The ID of the managed service.',
}),
staffId: t.exposeID('staffId', {
description: 'The ID of the staff member.',
mentorId: t.exposeID('mentorId', {
description: 'The ID of the mentor.',
}),
serviceId: t.exposeID('serviceId', {
description: 'The ID of the service.',
}),
staff: t.relation('staff', {
description: 'The staff member.',
schedule: t.relation('schedule', {
description: 'The schedule of the service.',
}),
mentor: t.relation('mentor', {
description: 'The mentor.',
}),
service: t.relation('service', {
description: 'The service.',

View File

@@ -44,6 +44,9 @@ export class ServiceSchema extends PothosSchema {
userId: t.exposeID('userId', {
description: 'The ID of the user who requested the service.',
}),
adminNote: t.relation('adminNote', {
description: 'The admin note of the service.',
}),
price: t.exposeFloat('price', {
description: 'The price of the service.',
}),
@@ -257,7 +260,7 @@ export class ServiceSchema extends PothosSchema {
: ServiceStatus.REJECTED,
},
});
// mail to center owner and staff who requested the service
// mail to center owner and mentor who requested the service
const center = await prisma.center.findUnique({
where: { id: service.centerId },
});
@@ -270,11 +273,11 @@ export class ServiceSchema extends PothosSchema {
if (!centerOwner) {
throw new Error('Center owner not found');
}
const centerStaff = await prisma.centerStaff.findMany({
const centerMentor = await prisma.centerMentor.findMany({
where: { centerId: service.centerId },
});
const staffEmails = centerStaff.map((staff) => staff.staffId);
const emails = [centerOwner.email, ...staffEmails];
const mentorEmails = centerMentor.map((mentor) => mentor.mentorId);
const emails = [centerOwner.email, ...mentorEmails];
for (const email of emails) {
await this.mailService.sendEmail(
email,

View File

@@ -80,15 +80,18 @@ export class UserSchema extends PothosSchema {
customerChatRoom: t.relation('customerChatRoom', {
description: 'The customer chat room of the user.',
}),
centerStaffChatRoom: t.relation('centerStaffChatRoom', {
description: 'The center staff chat room of the user.',
mentorChatRoom: t.relation('mentorChatRoom', {
description: 'The mentor chat room of the user.',
}),
centerStaff: t.relation('centerStaff', {
description: 'The center staff of the user.',
mentor: t.relation('mentor', {
description: 'The mentor of the user.',
}),
workshopSubscription: t.relation('workshopSubscription', {
description: 'The workshop subscription of the user.',
}),
adminNote: t.relation('adminNote', {
description: 'The admin note of the user.',
}),
}),
});
}
@@ -242,7 +245,7 @@ export class UserSchema extends PothosSchema {
await this.mailService.sendTemplateEmail(
args.to,
'Bạn đã được mời làm việc tại Trung tâm băng đĩa lậu hải ngoại',
'StaffInvitation',
'MentorInvitation',
{
center_name: 'băng đĩa lậu hải ngoại',
invite_url: 'https://epess.org',

View File

@@ -33,9 +33,8 @@ export class WorkshopSchema extends PothosSchema {
description: t.exposeString('description', {
description: 'The description of the workshop.',
}),
staffId: t.exposeID('staffId', {
description:
'The ID of the staff member who is leading the workshop.',
mentorId: t.exposeID('mentorId', {
description: 'The ID of the mentor who is leading the workshop.',
}),
serviceId: t.exposeID('serviceId', {
description: 'The ID of the service that the workshop is for.',
@@ -73,8 +72,8 @@ export class WorkshopSchema extends PothosSchema {
subscription: t.relation('subscription', {
description: 'The subscription that the workshop is for.',
}),
staff: t.relation('staff', {
description: 'The staff member who is leading the workshop.',
mentor: t.relation('mentor', {
description: 'The mentor who is leading the workshop.',
}),
meetingRoom: t.relation('workshopMeetingRoom', {
nullable: true,

File diff suppressed because one or more lines are too long