refactor: standardize formatting and improve readability in ScheduleSchema
- Reformatted import statements and code structure for consistency and clarity. - Enhanced field descriptions across the ScheduleSchema to ensure uniformity and better understanding. - Updated error messages for improved user feedback during scheduling operations. - Improved the organization of query and mutation fields for better maintainability. These changes aim to enhance code readability, maintainability, and user experience within the scheduling features.
This commit is contained in:
@@ -1,84 +1,93 @@
|
|||||||
import { Inject, Injectable, Logger } from '@nestjs/common'
|
import { Inject, Injectable, Logger } from "@nestjs/common";
|
||||||
import { CenterStatus, ScheduleDateStatus, ScheduleStatus } from '@prisma/client'
|
import {
|
||||||
import { Role } from '@prisma/client'
|
CenterStatus,
|
||||||
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
ScheduleDateStatus,
|
||||||
import { DateTimeUtils } from 'src/common/utils/datetime.utils'
|
ScheduleStatus,
|
||||||
import { AppConfigService } from '../AppConfig/appconfig.service'
|
} from "@prisma/client";
|
||||||
import { Builder } from '../Graphql/graphql.builder'
|
import { Role } from "@prisma/client";
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import {
|
||||||
import { ScheduleConfigType } from './schedule'
|
Pothos,
|
||||||
import { ScheduleService } from './schedule.service'
|
PothosRef,
|
||||||
|
PothosSchema,
|
||||||
|
SchemaBuilderToken,
|
||||||
|
} from "@smatch-corp/nestjs-pothos";
|
||||||
|
import { DateTimeUtils } from "src/common/utils/datetime.utils";
|
||||||
|
import { AppConfigService } from "../AppConfig/appconfig.service";
|
||||||
|
import { Builder } from "../Graphql/graphql.builder";
|
||||||
|
import { PrismaService } from "../Prisma/prisma.service";
|
||||||
|
import { ScheduleConfigType } from "./schedule";
|
||||||
|
import { ScheduleService } from "./schedule.service";
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScheduleSchema extends PothosSchema {
|
export class ScheduleSchema extends PothosSchema {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(SchemaBuilderToken) private readonly builder: Builder,
|
@Inject(SchemaBuilderToken) private readonly builder: Builder,
|
||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
private readonly scheduleService: ScheduleService,
|
private readonly scheduleService: ScheduleService,
|
||||||
private readonly appConfigService: AppConfigService,
|
private readonly appConfigService: AppConfigService
|
||||||
) {
|
) {
|
||||||
super()
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
schedule() {
|
schedule() {
|
||||||
return this.builder.prismaObject('Schedule', {
|
return this.builder.prismaObject("Schedule", {
|
||||||
description: 'A schedule in the system.',
|
description: "A schedule in the system.",
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
id: t.exposeID('id', {
|
id: t.exposeID("id", {
|
||||||
description: 'The ID of the schedule.',
|
description: "The ID of the schedule.",
|
||||||
}),
|
}),
|
||||||
customerId: t.exposeID('customerId', {
|
customerId: t.exposeID("customerId", {
|
||||||
description: 'The ID of the customer the schedule belongs to.',
|
description: "The ID of the customer the schedule belongs to.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
managedServiceId: t.exposeID('managedServiceId', {
|
managedServiceId: t.exposeID("managedServiceId", {
|
||||||
description: 'The ID of the managed service the schedule belongs to.',
|
description: "The ID of the managed service the schedule belongs to.",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
orderId: t.exposeID('orderId', {
|
orderId: t.exposeID("orderId", {
|
||||||
description: 'The ID of the order the schedule belongs to.',
|
description: "The ID of the order the schedule belongs to.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
order: t.relation('Order', {
|
order: t.relation("Order", {
|
||||||
description: 'The order that belongs to orderId.',
|
description: "The order that belongs to orderId.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
scheduleStart: t.expose('scheduleStart', {
|
scheduleStart: t.expose("scheduleStart", {
|
||||||
type: 'DateTime',
|
type: "DateTime",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
scheduleEnd: t.expose('scheduleEnd', {
|
scheduleEnd: t.expose("scheduleEnd", {
|
||||||
type: 'DateTime',
|
type: "DateTime",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
slots: t.exposeIntList('slots', {
|
slots: t.exposeIntList("slots", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
daysOfWeek: t.exposeIntList('daysOfWeek', {
|
daysOfWeek: t.exposeIntList("daysOfWeek", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
dates: t.relation('dates', {
|
dates: t.relation("dates", {
|
||||||
description: 'The dates of the schedule.',
|
description: "The dates of the schedule.",
|
||||||
}),
|
}),
|
||||||
status: t.expose('status', {
|
status: t.expose("status", {
|
||||||
type: ScheduleStatus,
|
type: ScheduleStatus,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
managedService: t.relation('managedService', {
|
managedService: t.relation("managedService", {
|
||||||
description: 'The managed service the schedule belongs to.',
|
description: "The managed service the schedule belongs to.",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
personalMilestone: t.relation('personalMilestone', {
|
personalMilestone: t.relation("personalMilestone", {
|
||||||
description: 'The personal milestone of the schedule.',
|
description: "The personal milestone of the schedule.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleConnection() {
|
scheduleConnection() {
|
||||||
return this.builder.simpleObject('ScheduleConnection', {
|
return this.builder.simpleObject("ScheduleConnection", {
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
totalCount: t.int({
|
totalCount: t.int({
|
||||||
nullable: true,
|
nullable: true,
|
||||||
@@ -87,93 +96,93 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
type: [this.schedule()],
|
type: [this.schedule()],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleSlot() {
|
scheduleSlot() {
|
||||||
return this.builder.simpleObject('ScheduleSlot', {
|
return this.builder.simpleObject("ScheduleSlot", {
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
slot: t.string({}),
|
slot: t.string({}),
|
||||||
start: t.string({}),
|
start: t.string({}),
|
||||||
end: t.string({}),
|
end: t.string({}),
|
||||||
dayOfWeek: t.int({}),
|
dayOfWeek: t.int({}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
previewSchedule() {
|
previewSchedule() {
|
||||||
return this.builder.simpleObject('PreviewSchedule', {
|
return this.builder.simpleObject("PreviewSchedule", {
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
totalSlots: t.int(),
|
totalSlots: t.int(),
|
||||||
slots: t.field({
|
slots: t.field({
|
||||||
type: [this.scheduleSlot()],
|
type: [this.scheduleSlot()],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleDate() {
|
scheduleDate() {
|
||||||
return this.builder.prismaObject('ScheduleDate', {
|
return this.builder.prismaObject("ScheduleDate", {
|
||||||
description: 'A schedule date in the system.',
|
description: "A schedule date in the system.",
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
id: t.exposeID('id', {
|
id: t.exposeID("id", {
|
||||||
description: 'The ID of the schedule date.',
|
description: "The ID of the schedule date.",
|
||||||
}),
|
}),
|
||||||
scheduleId: t.exposeID('scheduleId', {
|
scheduleId: t.exposeID("scheduleId", {
|
||||||
description: 'The ID of the schedule the schedule date belongs to.',
|
description: "The ID of the schedule the schedule date belongs to.",
|
||||||
}),
|
}),
|
||||||
start: t.expose('start', {
|
start: t.expose("start", {
|
||||||
type: 'DateTime',
|
type: "DateTime",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
end: t.expose('end', {
|
end: t.expose("end", {
|
||||||
type: 'DateTime',
|
type: "DateTime",
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
status: t.expose('status', {
|
status: t.expose("status", {
|
||||||
type: ScheduleDateStatus,
|
type: ScheduleDateStatus,
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
dayOfWeek: t.exposeInt('dayOfWeek', {
|
dayOfWeek: t.exposeInt("dayOfWeek", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
slot: t.exposeInt('slot', {
|
slot: t.exposeInt("slot", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
serviceId: t.exposeID('serviceId', {
|
serviceId: t.exposeID("serviceId", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
orderId: t.exposeID('orderId', {
|
orderId: t.exposeID("orderId", {
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
participantIds: t.exposeStringList('participantIds', {
|
participantIds: t.exposeStringList("participantIds", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
maxParticipants: t.exposeInt('maxParticipants', {
|
maxParticipants: t.exposeInt("maxParticipants", {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
}),
|
}),
|
||||||
lateStart: t.expose('lateStart', {
|
lateStart: t.expose("lateStart", {
|
||||||
type: 'DateTime',
|
type: "DateTime",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
collaborationSession: t.relation('CollaborationSession', {
|
collaborationSession: t.relation("CollaborationSession", {
|
||||||
description: 'The collaboration session of the schedule date.',
|
description: "The collaboration session of the schedule date.",
|
||||||
nullable: true,
|
nullable: true,
|
||||||
}),
|
}),
|
||||||
schedule: t.relation('schedule', {
|
schedule: t.relation("schedule", {
|
||||||
description: 'The schedule the schedule date belongs to.',
|
description: "The schedule the schedule date belongs to.",
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleConfigInput() {
|
scheduleConfigInput() {
|
||||||
return this.builder.inputType('ScheduleConfigInput', {
|
return this.builder.inputType("ScheduleConfigInput", {
|
||||||
description: 'A schedule config in the system.',
|
description: "A schedule config in the system.",
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
midDayBreakTimeStart: t.string({
|
midDayBreakTimeStart: t.string({
|
||||||
required: true,
|
required: true,
|
||||||
@@ -194,12 +203,12 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleConfigInputForCenter() {
|
scheduleConfigInputForCenter() {
|
||||||
return this.builder.inputType('ScheduleConfigInputForCenter', {
|
return this.builder.inputType("ScheduleConfigInputForCenter", {
|
||||||
fields: (t) => ({
|
fields: (t) => ({
|
||||||
startDate: t.string({
|
startDate: t.string({
|
||||||
required: true,
|
required: true,
|
||||||
@@ -214,7 +223,7 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Pothos()
|
@Pothos()
|
||||||
@@ -222,25 +231,30 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
this.builder.queryFields((t) => ({
|
this.builder.queryFields((t) => ({
|
||||||
schedule: t.prismaField({
|
schedule: t.prismaField({
|
||||||
type: this.schedule(),
|
type: this.schedule(),
|
||||||
description: 'Retrieve a single schedule by its unique identifier.',
|
description: "Retrieve a single schedule by its unique identifier.",
|
||||||
args: this.builder.generator.findUniqueArgs('Schedule'),
|
args: this.builder.generator.findUniqueArgs("Schedule"),
|
||||||
resolve: async (query, _root, args, ctx, _info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
if (!ctx.me) {
|
if (!ctx.me) {
|
||||||
throw new Error('User not found')
|
throw new Error("User not found");
|
||||||
}
|
}
|
||||||
// only return schedule belong to center
|
// only return schedule belong to center
|
||||||
|
|
||||||
const center = await this.prisma.center.findFirst({
|
const center = await this.prisma.center.findFirst({
|
||||||
where: {
|
where: {
|
||||||
AND: [
|
AND: [
|
||||||
{ OR: [{ centerOwnerId: ctx.me.id }, { centerMentors: { some: { mentorId: ctx.me.id } } }] },
|
{
|
||||||
|
OR: [
|
||||||
|
{ centerOwnerId: ctx.me.id },
|
||||||
|
{ centerMentors: { some: { mentorId: ctx.me.id } } },
|
||||||
|
],
|
||||||
|
},
|
||||||
{ centerStatus: CenterStatus.APPROVED },
|
{ centerStatus: CenterStatus.APPROVED },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
if (!center) {
|
if (!center) {
|
||||||
throw new Error('Center not found')
|
throw new Error("Center not found");
|
||||||
}
|
}
|
||||||
return await this.prisma.schedule.findUnique({
|
return await this.prisma.schedule.findUnique({
|
||||||
...query,
|
...query,
|
||||||
@@ -248,17 +262,18 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
id: args.where?.id,
|
id: args.where?.id,
|
||||||
managedService: { service: { centerId: center.id } },
|
managedService: { service: { centerId: center.id } },
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
schedules: t.prismaField({
|
schedules: t.prismaField({
|
||||||
type: [this.schedule()],
|
type: [this.schedule()],
|
||||||
args: this.builder.generator.findManyArgs('Schedule'),
|
args: this.builder.generator.findManyArgs("Schedule"),
|
||||||
description: 'Retrieve a list of schedules with optional filtering, ordering, and pagination.',
|
description:
|
||||||
|
"Retrieve a list of schedules with optional filtering, ordering, and pagination.",
|
||||||
resolve: async (query, _root, args, ctx, _info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
if (!ctx.me) {
|
if (!ctx.me) {
|
||||||
throw new Error('User not found')
|
throw new Error("User not found");
|
||||||
}
|
}
|
||||||
// use case 1: customer query schedules where customer is participant
|
// use case 1: customer query schedules where customer is participant
|
||||||
if (ctx.me.role === Role.CUSTOMER) {
|
if (ctx.me.role === Role.CUSTOMER) {
|
||||||
@@ -268,8 +283,8 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
skip: args.skip ?? undefined,
|
skip: args.skip ?? undefined,
|
||||||
take: args.take ?? undefined,
|
take: args.take ?? undefined,
|
||||||
where: args.filter ?? undefined,
|
where: args.filter ?? undefined,
|
||||||
})
|
});
|
||||||
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
|
||||||
if (ctx.me.role === Role.CENTER_MENTOR) {
|
if (ctx.me.role === Role.CENTER_MENTOR) {
|
||||||
@@ -281,9 +296,9 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
if (!center) {
|
if (!center) {
|
||||||
throw new Error('Center not found')
|
throw new Error("Center not found");
|
||||||
}
|
}
|
||||||
// get all schedules belong to center
|
// get all schedules belong to center
|
||||||
const schedules = await this.prisma.schedule.findMany({
|
const schedules = await this.prisma.schedule.findMany({
|
||||||
@@ -293,42 +308,50 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
orderBy: args.orderBy ?? undefined,
|
orderBy: args.orderBy ?? undefined,
|
||||||
where: {
|
where: {
|
||||||
AND: [
|
AND: [
|
||||||
{ managedService: { service: { centerId: center.id }, mentorId: ctx.me.id } },
|
{
|
||||||
|
managedService: {
|
||||||
|
service: { centerId: center.id },
|
||||||
|
mentorId: ctx.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
|
// use case 3: Center owner query all schedules belong to center
|
||||||
if (ctx.me.role === Role.CENTER_OWNER) {
|
if (ctx.me.role === Role.CENTER_OWNER) {
|
||||||
const center = await this.prisma.center.findFirst({
|
const center = await this.prisma.center.findFirst({
|
||||||
where: { centerOwnerId: ctx.me.id },
|
where: { centerOwnerId: ctx.me.id },
|
||||||
})
|
});
|
||||||
if (!center) {
|
if (!center) {
|
||||||
throw new Error('Center not found')
|
throw new Error("Center not found");
|
||||||
}
|
}
|
||||||
const schedules = await this.prisma.schedule.findMany({
|
const schedules = await this.prisma.schedule.findMany({
|
||||||
...query,
|
...query,
|
||||||
where: {
|
where: {
|
||||||
AND: [{ managedService: { service: { centerId: center.id } } }, ...(args.filter ? [args.filter] : [])],
|
AND: [
|
||||||
|
{ managedService: { service: { centerId: center.id } } },
|
||||||
|
...(args.filter ? [args.filter] : []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
orderBy: args.orderBy ?? undefined,
|
orderBy: args.orderBy ?? undefined,
|
||||||
skip: args.skip ?? undefined,
|
skip: args.skip ?? undefined,
|
||||||
take: args.take ?? undefined,
|
take: args.take ?? undefined,
|
||||||
})
|
});
|
||||||
return schedules
|
return schedules;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
scheduleDates: t.prismaField({
|
scheduleDates: t.prismaField({
|
||||||
type: [this.scheduleDate()],
|
type: [this.scheduleDate()],
|
||||||
description: 'Retrieve a list of schedule dates.',
|
description: "Retrieve a list of schedule dates.",
|
||||||
args: this.builder.generator.findManyArgs('ScheduleDate'),
|
args: this.builder.generator.findManyArgs("ScheduleDate"),
|
||||||
resolve: async (query, _root, args, ctx, _info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
if (!ctx.me) {
|
if (!ctx.me) {
|
||||||
throw new Error('User not found')
|
throw new Error("User not found");
|
||||||
}
|
}
|
||||||
return await this.prisma.scheduleDate.findMany({
|
return await this.prisma.scheduleDate.findMany({
|
||||||
...query,
|
...query,
|
||||||
@@ -336,15 +359,18 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
take: args.take ?? undefined,
|
take: args.take ?? undefined,
|
||||||
orderBy: args.orderBy ?? undefined,
|
orderBy: args.orderBy ?? undefined,
|
||||||
where: {
|
where: {
|
||||||
AND: [{ participantIds: { has: ctx.me.id } }, ...(args.filter ? [args.filter] : [])],
|
AND: [
|
||||||
|
{ participantIds: { has: ctx.me.id } },
|
||||||
|
...(args.filter ? [args.filter] : []),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
centerPreviewSchedule: t.field({
|
centerPreviewSchedule: t.field({
|
||||||
type: this.previewSchedule(),
|
type: this.previewSchedule(),
|
||||||
description: 'Preview a schedule for center mentor.',
|
description: "Preview a schedule for center mentor.",
|
||||||
args: {
|
args: {
|
||||||
scheduleConfigInput: t.arg({
|
scheduleConfigInput: t.arg({
|
||||||
type: this.scheduleConfigInputForCenter(),
|
type: this.scheduleConfigInputForCenter(),
|
||||||
@@ -352,13 +378,15 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (_parent, args, _context, _info) => {
|
resolve: async (_parent, args, _context, _info) => {
|
||||||
return await this.scheduleService.createSchedulePreviewForCenter(args.scheduleConfigInput)
|
return await this.scheduleService.createSchedulePreviewForCenter(
|
||||||
|
args.scheduleConfigInput
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
adminPreviewSchedule: t.field({
|
adminPreviewSchedule: t.field({
|
||||||
type: this.previewSchedule(),
|
type: this.previewSchedule(),
|
||||||
description: 'Preview a schedule for admin.',
|
description: "Preview a schedule for admin.",
|
||||||
args: {
|
args: {
|
||||||
scheduleConfig: t.arg({
|
scheduleConfig: t.arg({
|
||||||
type: this.scheduleConfigInput(),
|
type: this.scheduleConfigInput(),
|
||||||
@@ -367,16 +395,20 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
resolve: async (_parent, args, _context, _info) => {
|
resolve: async (_parent, args, _context, _info) => {
|
||||||
// if no scheduleConfig, use default config
|
// if no scheduleConfig, use default config
|
||||||
if (!args.scheduleConfig) {
|
if (!args.scheduleConfig) {
|
||||||
args.scheduleConfig = (await this.appConfigService.getVisibleConfigs()).reduce((acc, curr) => {
|
args.scheduleConfig = (
|
||||||
|
await this.appConfigService.getVisibleConfigs()
|
||||||
|
).reduce((acc, curr) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
acc[curr.key] = curr.value
|
acc[curr.key] = curr.value;
|
||||||
return acc
|
return acc;
|
||||||
}, {} as ScheduleConfigType)
|
}, {} as ScheduleConfigType);
|
||||||
}
|
}
|
||||||
return await this.scheduleService.createSchedulePreviewForSingleDay(args.scheduleConfig)
|
return await this.scheduleService.createSchedulePreviewForSingleDay(
|
||||||
|
args.scheduleConfig
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}))
|
}));
|
||||||
|
|
||||||
/* overlapping case
|
/* overlapping case
|
||||||
46836288-bb2c-4da6-892b-a559a480cbf8,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-11-22 00:00:00.000,2024-11-02 00:00:00.000,UNPUBLISHED,,"{3,5}",,"{2,4}"
|
46836288-bb2c-4da6-892b-a559a480cbf8,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-11-22 00:00:00.000,2024-11-02 00:00:00.000,UNPUBLISHED,,"{3,5}",,"{2,4}"
|
||||||
@@ -387,46 +419,58 @@ d72a864e-2f41-45ab-9c9b-bf0512a31883,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-1
|
|||||||
// Mutations
|
// Mutations
|
||||||
createSchedule: t.prismaField({
|
createSchedule: t.prismaField({
|
||||||
type: this.schedule(),
|
type: this.schedule(),
|
||||||
description: 'Create a new schedule.',
|
description: "Create a new schedule.",
|
||||||
args: {
|
args: {
|
||||||
schedule: t.arg({
|
schedule: t.arg({
|
||||||
type: this.builder.generator.getCreateInput('Schedule', ['id', 'status', 'customerId', 'orderId', 'dates']),
|
type: this.builder.generator.getCreateInput("Schedule", [
|
||||||
|
"id",
|
||||||
|
"status",
|
||||||
|
"customerId",
|
||||||
|
"orderId",
|
||||||
|
"dates",
|
||||||
|
]),
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, _root, args, ctx, _info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
if (!ctx.me) {
|
if (!ctx.me) {
|
||||||
throw new Error('User not found')
|
throw new Error("User not found");
|
||||||
}
|
}
|
||||||
Logger.log('args.schedule', args.schedule)
|
Logger.log("args.schedule", args.schedule);
|
||||||
// reject schedule if start date is today or in the past
|
// reject schedule if start date is today or in the past
|
||||||
if (DateTimeUtils.fromDate(args.schedule.scheduleStart as Date).day <= DateTimeUtils.now().day) {
|
if (
|
||||||
throw new Error('Start date is in the past or today')
|
DateTimeUtils.fromDate(args.schedule.scheduleStart as Date).day <=
|
||||||
|
DateTimeUtils.now().day
|
||||||
|
) {
|
||||||
|
throw new Error("Start date is in the past or today");
|
||||||
}
|
}
|
||||||
// generate preview and check if there is any overlapping with other schedules date in same service
|
// generate preview and check if there is any overlapping with other schedules date in same service
|
||||||
const previewSchedule = await this.scheduleService.createSchedulePreviewForCenter({
|
const previewSchedule =
|
||||||
startDate: args.schedule.scheduleStart as string,
|
await this.scheduleService.createSchedulePreviewForCenter({
|
||||||
endDate: args.schedule.scheduleEnd as string,
|
startDate: args.schedule.scheduleStart as string,
|
||||||
slots: args.schedule.slots as number[],
|
endDate: args.schedule.scheduleEnd as string,
|
||||||
days: args.schedule.daysOfWeek as number[],
|
slots: args.schedule.slots as number[],
|
||||||
})
|
days: args.schedule.daysOfWeek as number[],
|
||||||
const existingScheduleDates = await this.prisma.scheduleDate.findMany({
|
});
|
||||||
where: {
|
const existingScheduleDates = await this.prisma.scheduleDate.findMany(
|
||||||
AND: [
|
{
|
||||||
{ serviceId: args.schedule.managedService.connect?.id },
|
where: {
|
||||||
{
|
AND: [
|
||||||
status: {
|
{ serviceId: args.schedule.managedService.connect?.id },
|
||||||
notIn: [
|
{
|
||||||
ScheduleDateStatus.COMPLETED,
|
status: {
|
||||||
ScheduleDateStatus.MISSING_MENTOR,
|
notIn: [
|
||||||
ScheduleDateStatus.MISSING_CUSTOMER,
|
ScheduleDateStatus.COMPLETED,
|
||||||
ScheduleDateStatus.EXPIRED,
|
ScheduleDateStatus.MISSING_MENTOR,
|
||||||
],
|
ScheduleDateStatus.MISSING_CUSTOMER,
|
||||||
|
ScheduleDateStatus.EXPIRED,
|
||||||
|
],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
},
|
}
|
||||||
})
|
);
|
||||||
// check if there is any overlapping with existing schedule dates in same service using DateTimeUtils
|
// check if there is any overlapping with existing schedule dates in same service using DateTimeUtils
|
||||||
const isOverlapping = DateTimeUtils.isOverlaps(
|
const isOverlapping = DateTimeUtils.isOverlaps(
|
||||||
previewSchedule.slots.map((slot) => ({
|
previewSchedule.slots.map((slot) => ({
|
||||||
@@ -436,18 +480,57 @@ d72a864e-2f41-45ab-9c9b-bf0512a31883,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-1
|
|||||||
existingScheduleDates.map((date) => ({
|
existingScheduleDates.map((date) => ({
|
||||||
start: DateTimeUtils.fromDate(date.start),
|
start: DateTimeUtils.fromDate(date.start),
|
||||||
end: DateTimeUtils.fromDate(date.end),
|
end: DateTimeUtils.fromDate(date.end),
|
||||||
})),
|
}))
|
||||||
)
|
);
|
||||||
if (isOverlapping) {
|
if (isOverlapping) {
|
||||||
Logger.error('Overlapping schedule', 'ScheduleSchema')
|
Logger.error("Overlapping schedule", "ScheduleSchema");
|
||||||
throw new Error('Overlapping schedule')
|
throw new Error("Overlapping schedule");
|
||||||
|
}
|
||||||
|
const scheduleDatesInSchedule =
|
||||||
|
await this.prisma.scheduleDate.findMany({
|
||||||
|
where: {
|
||||||
|
scheduleId: args.schedule.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const overlapSchedule = await this.prisma.scheduleDate.findFirst({
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{
|
||||||
|
participantIds: {
|
||||||
|
has: ctx.me?.id ?? "",
|
||||||
|
},
|
||||||
|
orderId: {
|
||||||
|
not: null,
|
||||||
|
},
|
||||||
|
dayOfWeek: {
|
||||||
|
in: Array.isArray(args.schedule.daysOfWeek)
|
||||||
|
? args.schedule.daysOfWeek
|
||||||
|
: [],
|
||||||
|
},
|
||||||
|
slot: {
|
||||||
|
in: Array.isArray(args.schedule.slots)
|
||||||
|
? args.schedule.slots
|
||||||
|
: [],
|
||||||
|
},
|
||||||
|
scheduleId: {
|
||||||
|
notIn: scheduleDatesInSchedule.map(
|
||||||
|
(scheduleDate) => scheduleDate.scheduleId
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (overlapSchedule) {
|
||||||
|
throw new Error("Overlapping schedule");
|
||||||
}
|
}
|
||||||
const schedule = await this.prisma.schedule.create({
|
const schedule = await this.prisma.schedule.create({
|
||||||
...query,
|
...query,
|
||||||
data: args.schedule,
|
data: args.schedule,
|
||||||
})
|
});
|
||||||
// generate schedule dates based on data and config
|
// generate schedule dates based on data and config
|
||||||
const scheduleDates = await this.scheduleService.generateScheduleDates(schedule)
|
const scheduleDates =
|
||||||
|
await this.scheduleService.generateScheduleDates(schedule);
|
||||||
// update schedule with schedule dates
|
// update schedule with schedule dates
|
||||||
return await this.prisma.schedule.update({
|
return await this.prisma.schedule.update({
|
||||||
...query,
|
...query,
|
||||||
@@ -457,16 +540,16 @@ d72a864e-2f41-45ab-9c9b-bf0512a31883,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-1
|
|||||||
connect: scheduleDates.map((date) => ({ id: date.id })),
|
connect: scheduleDates.map((date) => ({ id: date.id })),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
updateScheduleStatus: t.prismaField({
|
updateScheduleStatus: t.prismaField({
|
||||||
type: this.schedule(),
|
type: this.schedule(),
|
||||||
description: 'Update a schedule status.',
|
description: "Update a schedule status.",
|
||||||
args: {
|
args: {
|
||||||
scheduleId: t.arg({
|
scheduleId: t.arg({
|
||||||
type: 'String',
|
type: "String",
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
status: t.arg({
|
status: t.arg({
|
||||||
@@ -479,9 +562,9 @@ d72a864e-2f41-45ab-9c9b-bf0512a31883,e9be51fd-2382-4e43-9988-74e76fde4b56,2024-1
|
|||||||
...query,
|
...query,
|
||||||
where: { id: args.scheduleId },
|
where: { id: args.scheduleId },
|
||||||
data: { status: args.status },
|
data: { status: args.status },
|
||||||
})
|
});
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}))
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user