chore: fix order and schedule creation logic

This commit is contained in:
2024-12-16 16:26:18 +07:00
parent 07158bef3a
commit 11f234522b
6 changed files with 1411 additions and 1307 deletions

View File

@@ -1,13 +1,41 @@
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { CenterModule } from 'src/Center/center.module'
import { CenterSchema } from 'src/Center/center.schema' import { CenterSchema } from 'src/Center/center.schema'
import { CenterMentorModule } from 'src/CenterMentor/centermentor.module'
import { CenterMentorSchema } from 'src/CenterMentor/centermentor.schema'
import { ChatroomModule } from 'src/ChatRoom/chatroom.module'
import { ChatroomSchema } from 'src/ChatRoom/chatroom.schema'
import { MessageModule } from 'src/Message/message.module'
import { MessageSchema } from 'src/Message/message.schema'
import { OrderModule } from 'src/Order/order.module'
import { OrderSchema } from 'src/Order/order.schema' import { OrderSchema } from 'src/Order/order.schema'
import { PayosModule } from 'src/Payos/payos.module' import { PayosModule } from 'src/Payos/payos.module'
import { ServiceModule } from 'src/Service/service.module'
import { ServiceSchema } from 'src/Service/service.schema' import { ServiceSchema } from 'src/Service/service.schema'
import { UserModule } from 'src/User/user.module'
import { UserSchema } from 'src/User/user.schema'
import { AnalyticSchema } from './analytic.schema' import { AnalyticSchema } from './analytic.schema'
@Module({ @Module({
imports: [PayosModule], imports: [
providers: [AnalyticSchema, ServiceSchema, CenterSchema, OrderSchema], PayosModule,
exports: [AnalyticSchema, ServiceSchema, CenterSchema, OrderSchema], ServiceModule,
CenterModule,
OrderModule,
CenterMentorModule,
UserModule,
MessageModule,
ChatroomModule,
],
providers: [
AnalyticSchema,
ServiceSchema,
CenterSchema,
OrderSchema,
CenterMentorSchema,
UserSchema,
MessageSchema,
ChatroomSchema,
],
exports: [AnalyticSchema],
}) })
export class AnalyticModule {} export class AnalyticModule {}

View File

@@ -1,9 +1,17 @@
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { CenterSchema } from 'src/Center/center.schema'
import { CenterMentorSchema } from 'src/CenterMentor/centermentor.schema'
import { ChatroomSchema } from 'src/ChatRoom/chatroom.schema'
import { MessageModule } from 'src/Message/message.module'
import { MessageSchema } from 'src/Message/message.schema'
import { PayosModule } from 'src/Payos/payos.module' import { PayosModule } from 'src/Payos/payos.module'
import { UserModule } from 'src/User/user.module'
import { UserSchema } from 'src/User/user.schema'
import { OrderSchema } from './order.schema' import { OrderSchema } from './order.schema'
@Module({ @Module({
imports: [PayosModule], imports: [PayosModule, UserModule, MessageModule],
providers: [OrderSchema], providers: [OrderSchema, CenterSchema, CenterMentorSchema, UserSchema, MessageSchema, ChatroomSchema],
exports: [OrderSchema], exports: [OrderSchema],
}) })
export class OrderModule {} export class OrderModule {}

View File

@@ -2,6 +2,9 @@ import { Inject, Injectable, Logger } from '@nestjs/common'
import { OrderStatus, Role, ScheduleDateStatus, ScheduleStatus } from '@prisma/client' import { OrderStatus, Role, ScheduleDateStatus, ScheduleStatus } from '@prisma/client'
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos' import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
import _ from 'lodash' import _ from 'lodash'
import { CenterSchema } from 'src/Center/center.schema'
import { CenterMentorSchema } from 'src/CenterMentor/centermentor.schema'
import { UserSchema } from 'src/User/user.schema'
import { Builder } from '../Graphql/graphql.builder' import { Builder } from '../Graphql/graphql.builder'
import { PayosService } from '../Payos/payos.service' import { PayosService } from '../Payos/payos.service'
import { PrismaService } from '../Prisma/prisma.service' import { PrismaService } from '../Prisma/prisma.service'
@@ -12,6 +15,9 @@ export class OrderSchema extends PothosSchema {
@Inject(SchemaBuilderToken) private readonly builder: Builder, @Inject(SchemaBuilderToken) private readonly builder: Builder,
private readonly prisma: PrismaService, private readonly prisma: PrismaService,
private readonly payosService: PayosService, private readonly payosService: PayosService,
private readonly centerSchema: CenterSchema,
private readonly centerMentorSchema: CenterMentorSchema,
private readonly userSchema: UserSchema,
) { ) {
super() super()
} }
@@ -83,6 +89,37 @@ export class OrderSchema extends PothosSchema {
}) })
} }
@PothosRef()
orderDetails() {
return this.builder.simpleObject('OrderDetails', {
fields: (t) => ({
order: t.field({
type: this.order(),
description: 'The order of the details.',
}),
center: t.field({
type: this.centerSchema.center(),
description: 'The center of the order.',
}),
centerMentor: t.field({
type: this.centerMentorSchema.centerMentor(),
description: 'The mentor of the order.',
}),
user: t.field({
type: this.userSchema.user(),
description: 'The user of the order.',
}),
status: t.string(),
total: t.int(),
commission: t.float(),
completedAt: t.field({
type: 'DateTime',
description: 'The date and time the order was completed.',
}),
}),
})
}
@Pothos() @Pothos()
init(): void { init(): void {
// query section // query section
@@ -192,6 +229,119 @@ export class OrderSchema extends PothosSchema {
}) })
}, },
}), }),
completedOrdersDetails: t.field({
type: this.orderDetails(),
args: {
orderId: t.arg({
type: 'String',
required: true,
}),
},
description: 'Retrieve a list of completed orders details',
resolve: async (_query, args, ctx, _info) => {
if (ctx.isSubscription) {
throw new Error('Orders cannot be retrieved in subscription context')
}
if (!ctx.http.me) {
throw new Error('Unauthorized')
}
if (ctx.http.me.role !== Role.MODERATOR) {
throw new Error('Unauthorized')
}
// get order details
const order = await this.prisma.order.findUnique({
where: { id: args.orderId },
include: {
service: true,
schedule: {
include: {
managedService: true,
},
},
},
})
if (!order) {
throw new Error('Order not found')
}
// get center details
const center = await this.prisma.center.findUnique({
where: { id: order?.service?.centerId },
})
if (!center) {
throw new Error('Center not found')
}
// get mentor id from schedule
const mentorId = order?.schedule?.managedService?.mentorId
// get center mentor details
const centerMentor = await this.prisma.user.findUnique({
where: {
id: mentorId,
},
})
if (!centerMentor) {
throw new Error('Center mentor not found')
}
// get service details
const service = await this.prisma.service.findUnique({
where: { id: order?.serviceId },
})
if (!service) {
throw new Error('Service not found')
}
// calculate commission based on service price
const commission = service.price * (service.commission ?? 0.0)
// calculate total price
const total = service.price - commission
// get user details
const user = await this.prisma.user.findUnique({
where: { id: order?.userId },
})
if (!user) {
throw new Error('User not found')
}
return {
order: {
id: order.id,
userId: order.userId,
serviceId: order.serviceId,
status: order.status,
total: total,
commission: commission,
scheduleId: order.scheduleId,
chatRoomId: order.chatRoomId,
createdAt: order.createdAt,
updatedAt: order.updatedAt,
disbursed: order.disbursed,
paymentId: order.paymentId,
},
center,
centerMentor: {
centerId: center.id,
mentorId: centerMentor.id,
active: true, // default value
bio: null, // default value
isCenterOwner: false, // default value
name: centerMentor.name,
id: centerMentor.id,
createdAt: centerMentor.createdAt,
updatedAt: centerMentor.updatedAt,
email: centerMentor.email,
phoneNumber: centerMentor.phoneNumber,
bankBin: centerMentor.bankBin,
bankAccountNumber: centerMentor.bankAccountNumber,
role: centerMentor.role,
avatarUrl: centerMentor.avatarUrl,
scheduleDateId: centerMentor.scheduleDateId,
banned: centerMentor.banned,
},
user,
status: order.status,
total,
commission,
completedAt: order.schedule?.scheduleEnd,
}
},
}),
})) }))
// mutation section // mutation section
@@ -368,7 +518,16 @@ export class OrderSchema extends PothosSchema {
required: true, required: true,
}), }),
}, },
resolve: async (query, _root, args, _ctx, _info) => { resolve: async (query, _root, args, ctx, _info) => {
if (ctx.isSubscription) {
throw new Error('Subscription is not allowed')
}
if (!ctx.http.me) {
throw new Error('Unauthorized')
}
if (ctx.http.me.role !== Role.MODERATOR) {
throw new Error('Unauthorized')
}
return await this.prisma.order.update({ return await this.prisma.order.update({
...query, ...query,
data: args.data, data: args.data,

View File

@@ -278,13 +278,14 @@ export class ScheduleSchema extends PothosSchema {
return schedules return schedules
} }
// use case 2: center mentor or center owner query schedules where center mentor or center owner is mentor // use case 2: center mentor or center owner query schedules where center mentor or center owner is mentor
else if (ctx.http.me.role === Role.CENTER_MENTOR || ctx.http.me.role === Role.CENTER_OWNER) { if (ctx.http.me.role === Role.CENTER_MENTOR) {
const center = await this.prisma.center.findFirst({ const center = await this.prisma.center.findFirst({
where: { where: {
OR: [{ centerOwnerId: ctx.http.me.id }, { centerMentors: { some: { mentorId: ctx.http.me.id } } }], centerMentors: {
some: {
mentorId: ctx.http.me.id,
},
}, },
include: {
centerMentors: true,
}, },
}) })
if (!center) { if (!center) {
@@ -298,19 +299,32 @@ export class ScheduleSchema extends PothosSchema {
orderBy: args.orderBy ?? undefined, orderBy: args.orderBy ?? undefined,
where: { where: {
AND: [ AND: [
{ managedService: { service: { centerId: center.id } } }, { managedService: { service: { centerId: center.id }, mentorId: ctx.http.me.id } },
{
OR: [
{ customerId: ctx.http.me.id },
{ dates: { some: { participantIds: { has: ctx.http.me.id } } } },
],
},
...(args.filter ? [args.filter] : []), ...(args.filter ? [args.filter] : []),
], ],
}, },
}) })
return schedules return schedules
} }
// use case 3: Center owner query all schedules belong to center
if (ctx.http.me.role === Role.CENTER_OWNER) {
const center = await this.prisma.center.findFirst({
where: { centerOwnerId: ctx.http.me.id },
})
if (!center) {
throw new Error('Center not found')
}
const schedules = await this.prisma.schedule.findMany({
...query,
where: {
AND: [{ managedService: { service: { centerId: center.id } } }, ...(args.filter ? [args.filter] : [])],
},
orderBy: args.orderBy ?? undefined,
skip: args.skip ?? undefined,
take: args.take ?? undefined,
})
return schedules
}
}, },
}), }),

File diff suppressed because one or more lines are too long