update preview date
This commit is contained in:
8
package-lock.json
generated
8
package-lock.json
generated
@@ -77,6 +77,7 @@
|
|||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/jest": "^29.5.2",
|
"@types/jest": "^29.5.2",
|
||||||
|
"@types/lodash": "^4.17.13",
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.1",
|
||||||
"@types/nodemailer": "^6.4.16",
|
"@types/nodemailer": "^6.4.16",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
@@ -5534,6 +5535,13 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/lodash": {
|
||||||
|
"version": "4.17.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
|
||||||
|
"integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/long": {
|
"node_modules/@types/long": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -99,6 +99,7 @@
|
|||||||
"@types/bcryptjs": "^2.4.6",
|
"@types/bcryptjs": "^2.4.6",
|
||||||
"@types/express": "^4.17.17",
|
"@types/express": "^4.17.17",
|
||||||
"@types/jest": "^29.5.2",
|
"@types/jest": "^29.5.2",
|
||||||
|
"@types/lodash": "^4.17.13",
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.1",
|
||||||
"@types/nodemailer": "^6.4.16",
|
"@types/nodemailer": "^6.4.16",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
@@ -123,13 +124,19 @@
|
|||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"moduleFileExtensions": ["js", "json", "ts"],
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
"rootDir": "src",
|
"rootDir": "src",
|
||||||
"testRegex": ".*\\.spec\\.ts$",
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
"transform": {
|
"transform": {
|
||||||
"^.+\\.(t|j)s$": "ts-jest"
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
},
|
},
|
||||||
"collectCoverageFrom": ["**/*.(t|j)s"],
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
"coverageDirectory": "../coverage",
|
"coverageDirectory": "../coverage",
|
||||||
"testEnvironment": "node"
|
"testEnvironment": "node"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,25 +22,25 @@ export const ConfigConstants: Record<
|
|||||||
MID_DAY_BREAK_TIME_START: {
|
MID_DAY_BREAK_TIME_START: {
|
||||||
name: 'Mid Day Break Time Start',
|
name: 'Mid Day Break Time Start',
|
||||||
key: 'MID_DAY_BREAK_TIME_START',
|
key: 'MID_DAY_BREAK_TIME_START',
|
||||||
value: new Date(new Date().setHours(12, 0, 0, 0)).toISOString(),
|
value: new Date(new Date().setUTCHours(12, 0, 0, 0)).toISOString(),
|
||||||
visible: true,
|
visible: true,
|
||||||
},
|
},
|
||||||
MID_DAY_BREAK_TIME_END: {
|
MID_DAY_BREAK_TIME_END: {
|
||||||
name: 'Mid Day Break Time End',
|
name: 'Mid Day Break Time End',
|
||||||
key: 'MID_DAY_BREAK_TIME_END',
|
key: 'MID_DAY_BREAK_TIME_END',
|
||||||
value: new Date(new Date().setHours(13, 0, 0, 0)).toISOString(),
|
value: new Date(new Date().setUTCHours(13, 0, 0, 0)).toISOString(),
|
||||||
visible: true,
|
visible: true,
|
||||||
},
|
},
|
||||||
SLOT_START_TIME: {
|
SLOT_START_TIME: {
|
||||||
name: 'Slot Start Time',
|
name: 'Slot Start Time',
|
||||||
key: 'SLOT_START_TIME',
|
key: 'SLOT_START_TIME',
|
||||||
value: new Date(new Date().setHours(8, 0, 0, 0)).toISOString(),
|
value: new Date(new Date().setUTCHours(8, 0, 0, 0)).toISOString(),
|
||||||
visible: true,
|
visible: true,
|
||||||
},
|
},
|
||||||
SLOT_END_TIME: {
|
SLOT_END_TIME: {
|
||||||
name: 'Slot End Time',
|
name: 'Slot End Time',
|
||||||
key: 'SLOT_END_TIME',
|
key: 'SLOT_END_TIME',
|
||||||
value: new Date(new Date().setHours(22, 0, 0, 0)).toISOString(),
|
value: new Date(new Date().setUTCHours(22, 0, 0, 0)).toISOString(),
|
||||||
visible: true,
|
visible: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ export class AppConfigService implements OnModuleInit {
|
|||||||
where: { key },
|
where: { key },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
async getConfigValue(key: string) {
|
||||||
|
return (await this.getConfig(key))?.value
|
||||||
|
}
|
||||||
|
|
||||||
async getVisibleConfigs() {
|
async getVisibleConfigs() {
|
||||||
return await this.prisma.config.findMany({
|
return await this.prisma.config.findMany({
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Module } from '@nestjs/common'
|
import { Module } from '@nestjs/common'
|
||||||
import { ScheduleSchema } from './schedule.schema'
|
import { ScheduleSchema } from './schedule.schema'
|
||||||
|
import { ScheduleService } from './schedule.service'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [ScheduleSchema],
|
providers: [ScheduleSchema, ScheduleService],
|
||||||
exports: [ScheduleSchema],
|
exports: [ScheduleSchema, ScheduleService],
|
||||||
})
|
})
|
||||||
export class ScheduleModule {}
|
export class ScheduleModule {}
|
||||||
|
|||||||
@@ -8,12 +8,39 @@ import {
|
|||||||
import { Builder } from '../Graphql/graphql.builder'
|
import { Builder } from '../Graphql/graphql.builder'
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import { PrismaService } from '../Prisma/prisma.service'
|
||||||
import { ScheduleStatus } from '@prisma/client'
|
import { ScheduleStatus } from '@prisma/client'
|
||||||
|
import { ScheduleService } from './schedule.service'
|
||||||
|
import { AppConfigService } from '../AppConfig/appconfig.service'
|
||||||
|
|
||||||
|
export type ScheduleConfigType =
|
||||||
|
| {
|
||||||
|
midDayBreakTimeStart?: string | null | undefined
|
||||||
|
midDayBreakTimeEnd?: string | null | undefined
|
||||||
|
slotDuration?: string | null | undefined
|
||||||
|
slotBreakDuration?: string | null | undefined
|
||||||
|
slotEndTime?: string | null | undefined
|
||||||
|
slotStartTime?: string | null | undefined
|
||||||
|
}
|
||||||
|
| null
|
||||||
|
| undefined
|
||||||
|
|
||||||
|
export type ScheduleSlotType = {
|
||||||
|
slot: string
|
||||||
|
start: string
|
||||||
|
end: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PreviewScheduleType = {
|
||||||
|
totalSlots: number
|
||||||
|
slots: ScheduleSlotType[]
|
||||||
|
}
|
||||||
|
|
||||||
@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 appConfigService: AppConfigService,
|
||||||
) {
|
) {
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
@@ -53,6 +80,29 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PothosRef()
|
||||||
|
scheduleSlot() {
|
||||||
|
return this.builder.simpleObject('ScheduleSlot', {
|
||||||
|
fields: (t) => ({
|
||||||
|
slot: t.string({}),
|
||||||
|
start: t.string({}),
|
||||||
|
end: t.string({}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@PothosRef()
|
||||||
|
previewSchedule() {
|
||||||
|
return this.builder.simpleObject('PreviewSchedule', {
|
||||||
|
fields: (t) => ({
|
||||||
|
totalSlots: t.int(),
|
||||||
|
slots: t.field({
|
||||||
|
type: [this.scheduleSlot()],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@PothosRef()
|
@PothosRef()
|
||||||
scheduleDate() {
|
scheduleDate() {
|
||||||
return this.builder.prismaObject('ScheduleDate', {
|
return this.builder.prismaObject('ScheduleDate', {
|
||||||
@@ -79,6 +129,21 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PothosRef()
|
||||||
|
scheduleConfigInput() {
|
||||||
|
return this.builder.inputType('ScheduleConfigInput', {
|
||||||
|
description: 'A schedule config in the system.',
|
||||||
|
fields: (t) => ({
|
||||||
|
midDayBreakTimeStart: t.string(),
|
||||||
|
midDayBreakTimeEnd: t.string(),
|
||||||
|
slotDuration: t.string(),
|
||||||
|
slotBreakDuration: t.string(),
|
||||||
|
slotEndTime: t.string(),
|
||||||
|
slotStartTime: t.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
@Pothos()
|
@Pothos()
|
||||||
init(): void {
|
init(): void {
|
||||||
this.builder.queryFields((t) => ({
|
this.builder.queryFields((t) => ({
|
||||||
@@ -109,6 +174,21 @@ export class ScheduleSchema extends PothosSchema {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
adminPreviewSchedule: t.field({
|
||||||
|
type: this.previewSchedule(),
|
||||||
|
description: 'Preview a schedule for admin.',
|
||||||
|
args: {
|
||||||
|
scheduleConfig: t.arg({
|
||||||
|
type: this.scheduleConfigInput(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
resolve: async (_parent, args, _context, _info) => {
|
||||||
|
return await this.scheduleService.createSchedulePreview(
|
||||||
|
args.scheduleConfig,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import * as DateTimeUtils from '../common/utils/datetime.utils'
|
import * as DateTimeUtils from '../common/utils/datetime.utils'
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common'
|
import { Injectable, Logger } from '@nestjs/common'
|
||||||
import { PrismaService } from 'src/Prisma/prisma.service'
|
import { PrismaService } from 'src/Prisma/prisma.service'
|
||||||
import { Schedule } from '@prisma/client'
|
|
||||||
|
|
||||||
import { AppConfigService } from 'src/AppConfig/appconfig.service'
|
import { AppConfigService } from 'src/AppConfig/appconfig.service'
|
||||||
|
import {
|
||||||
|
PreviewScheduleType,
|
||||||
|
ScheduleConfigType,
|
||||||
|
ScheduleSlotType,
|
||||||
|
} from './schedule.schema'
|
||||||
|
import { Config } from '@prisma/client'
|
||||||
|
import * as _ from 'lodash'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ScheduleService {
|
export class ScheduleService {
|
||||||
@@ -13,10 +19,176 @@ export class ScheduleService {
|
|||||||
private readonly appConfigService: AppConfigService,
|
private readonly appConfigService: AppConfigService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createSchedule(schedule: Schedule) {
|
async createSchedulePreview(
|
||||||
// get config
|
scheduleConfig: ScheduleConfigType,
|
||||||
const config = await this.appConfigService.getVisibleConfigs()
|
): Promise<PreviewScheduleType> {
|
||||||
console.log(config)
|
const config: Config[] = await this.appConfigService.getVisibleConfigs()
|
||||||
|
Logger.log(config)
|
||||||
|
// process scheduleConfig input by filling with default values from config
|
||||||
|
const scheduleConfigFilled = this.processScheduleConfig(
|
||||||
|
scheduleConfig,
|
||||||
|
config,
|
||||||
|
)
|
||||||
// generate Slot By config
|
// generate Slot By config
|
||||||
|
const slots = this.generateSlots(scheduleConfigFilled)
|
||||||
|
|
||||||
|
return {
|
||||||
|
totalSlots: slots.length,
|
||||||
|
slots: slots,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
generateSlots(scheduleConfigFilled: ScheduleConfigType): ScheduleSlotType[] {
|
||||||
|
Logger.log(`Generating slots with config: ${scheduleConfigFilled}`)
|
||||||
|
const slots: ScheduleSlotType[] = []
|
||||||
|
const numberOfSlots = this.calculateNumberOfSlots(
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotStartTime,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotEndTime,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotDuration,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotBreakDuration,
|
||||||
|
)
|
||||||
|
for (let i = 1; i <= numberOfSlots; i++) {
|
||||||
|
const { startTime, endTime } = this.getSlotStartAndEndTime(
|
||||||
|
i,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotDuration,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotBreakDuration,
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.slotStartTime,
|
||||||
|
)
|
||||||
|
// if the slot is not overlapping with mid day break time, add it to the slots
|
||||||
|
if (
|
||||||
|
!this.isOverLapping(
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
this.getSpecificDateWithTime(
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.midDayBreakTimeStart,
|
||||||
|
),
|
||||||
|
this.getSpecificDateWithTime(
|
||||||
|
// @ts-ignore
|
||||||
|
scheduleConfigFilled?.midDayBreakTimeEnd,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
slots.push({
|
||||||
|
slot: i.toString(),
|
||||||
|
start: startTime.toISOString(),
|
||||||
|
end: endTime.toISOString(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return slots
|
||||||
|
}
|
||||||
|
|
||||||
|
isOverLapping(
|
||||||
|
startTime1: Date,
|
||||||
|
endTime1: Date,
|
||||||
|
startTime2: Date,
|
||||||
|
endTime2: Date,
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
Math.max(startTime1.getTime(), startTime2.getTime()) <
|
||||||
|
Math.min(endTime1.getTime(), endTime2.getTime())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateNumberOfSlots(
|
||||||
|
startTime: string,
|
||||||
|
endTime: string,
|
||||||
|
slotDuration: string,
|
||||||
|
slotBreakDuration: string,
|
||||||
|
) {
|
||||||
|
const startDate = new Date(startTime)
|
||||||
|
const endDate = new Date(endTime)
|
||||||
|
|
||||||
|
const totalMinutes = (endDate.getTime() - startDate.getTime()) / (60 * 1000)
|
||||||
|
const numberOfSlots = Math.floor(
|
||||||
|
totalMinutes / (parseInt(slotDuration) + parseInt(slotBreakDuration)),
|
||||||
|
)
|
||||||
|
return numberOfSlots
|
||||||
|
}
|
||||||
|
|
||||||
|
getSlotStartAndEndTime(
|
||||||
|
slotNumber: number,
|
||||||
|
slotDuration: string,
|
||||||
|
slotBreakDuration: string,
|
||||||
|
slotStartTime: string,
|
||||||
|
) {
|
||||||
|
const startTime = new Date(slotStartTime)
|
||||||
|
startTime.setUTCMinutes(
|
||||||
|
startTime.getUTCMinutes() +
|
||||||
|
slotNumber * (parseInt(slotDuration) + parseInt(slotBreakDuration)),
|
||||||
|
)
|
||||||
|
const endTime = new Date(startTime)
|
||||||
|
endTime.setUTCMinutes(endTime.getUTCMinutes() + parseInt(slotDuration))
|
||||||
|
return { startTime, endTime }
|
||||||
|
}
|
||||||
|
|
||||||
|
processScheduleConfig(
|
||||||
|
scheduleConfig: ScheduleConfigType,
|
||||||
|
config: Config[],
|
||||||
|
): ScheduleConfigType {
|
||||||
|
// if scheduleConfig is undefined, create a new object and seed all the values with default values from config
|
||||||
|
if (scheduleConfig === undefined) {
|
||||||
|
scheduleConfig = config.reduce((acc, curr) => {
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
;(acc as any)[this.sneakyCaseToCamelCase(curr.key)] = curr.value
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
// loop through scheduleConfig and fill with default values from config
|
||||||
|
for (const key in scheduleConfig) {
|
||||||
|
if (
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
(scheduleConfig as any)[key] === undefined ||
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
(scheduleConfig as any)[key] === null ||
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
(scheduleConfig as any)[key] === ''
|
||||||
|
) {
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
;(scheduleConfig as any)[key] =
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
||||||
|
config[this.camelCaseToUpperSneakyCase(key) as any]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scheduleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
camelCaseToUpperSneakyCase(str: string) {
|
||||||
|
return _.snakeCase(str).toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
sneakyCaseToCamelCase(str: string) {
|
||||||
|
return _.camelCase(str.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
getTodayWithTime(date: Date) {
|
||||||
|
const today = new Date()
|
||||||
|
today.setUTCHours(
|
||||||
|
date.getUTCHours(),
|
||||||
|
date.getUTCMinutes(),
|
||||||
|
date.getUTCSeconds(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
return today
|
||||||
|
}
|
||||||
|
|
||||||
|
getSpecificDateWithTime(date: Date) {
|
||||||
|
const specificDate = new Date(date)
|
||||||
|
date = new Date(date)
|
||||||
|
specificDate.setUTCHours(
|
||||||
|
date.getUTCHours(),
|
||||||
|
date.getUTCMinutes(),
|
||||||
|
date.getUTCSeconds(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
return specificDate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
import { Builder } from '../Graphql/graphql.builder'
|
import { Builder } from '../Graphql/graphql.builder'
|
||||||
import { PrismaService } from '../Prisma/prisma.service'
|
import { PrismaService } from '../Prisma/prisma.service'
|
||||||
import { MinioService } from '../Minio/minio.service'
|
import { MinioService } from '../Minio/minio.service'
|
||||||
import { ServiceStatus } from '@prisma/client'
|
import { Role, ServiceStatus } from '@prisma/client'
|
||||||
import { MailService } from '../Mail/mail.service'
|
import { MailService } from '../Mail/mail.service'
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServiceSchema extends PothosSchema {
|
export class ServiceSchema extends PothosSchema {
|
||||||
@@ -119,7 +119,7 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
type: this.service(),
|
type: this.service(),
|
||||||
cursor: 'id',
|
cursor: 'id',
|
||||||
args: this.builder.generator.findManyArgs('Service'),
|
args: this.builder.generator.findManyArgs('Service'),
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, _args, _ctx, _info) => {
|
||||||
return await this.prisma.service.findMany({
|
return await this.prisma.service.findMany({
|
||||||
...query,
|
...query,
|
||||||
})
|
})
|
||||||
@@ -136,9 +136,57 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
description:
|
description:
|
||||||
'Retrieve a list of services with optional filtering, ordering, and pagination.',
|
'Retrieve a list of services with optional filtering, ordering, and pagination.',
|
||||||
type: [this.service()],
|
type: [this.service()],
|
||||||
|
args: this.builder.generator.findManyArgs('Service'),
|
||||||
|
resolve: async (query, _root, args, _ctx, _info) => {
|
||||||
|
return await this.prisma.service.findMany({
|
||||||
|
...query,
|
||||||
|
where: args.filter ?? undefined,
|
||||||
|
orderBy: args.orderBy ?? undefined,
|
||||||
|
skip: args.skip ?? undefined,
|
||||||
|
take: args.take ?? undefined,
|
||||||
|
cursor: args.cursor ?? undefined,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
servicesByCenter: t.prismaField({
|
||||||
|
description:
|
||||||
|
'Retrieve a list of services with optional filtering, ordering, and pagination.',
|
||||||
|
type: [this.service()],
|
||||||
|
|
||||||
args: this.builder.generator.findManyArgs('Service'),
|
args: this.builder.generator.findManyArgs('Service'),
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
|
if (ctx.isSubscription) {
|
||||||
|
throw new Error('Not allowed')
|
||||||
|
}
|
||||||
|
// check role if user is mentor or center owner
|
||||||
|
const role = ctx.http.me.role
|
||||||
|
if (role !== Role.CENTER_MENTOR && role !== Role.CENTER_OWNER) {
|
||||||
|
throw new Error('Not allowed')
|
||||||
|
}
|
||||||
|
if (role === Role.CENTER_MENTOR) {
|
||||||
|
// load only service belong to center of current user
|
||||||
|
const managedServices = await this.prisma.managedService.findMany({
|
||||||
|
where: { mentorId: ctx.http.me.id },
|
||||||
|
})
|
||||||
|
if (!managedServices) {
|
||||||
|
throw new Error('Managed services not found')
|
||||||
|
}
|
||||||
|
// query services that have serviceId in managedServices
|
||||||
|
args.filter = {
|
||||||
|
id: { in: managedServices.map((service) => service.serviceId) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if role is center owner, load all services belong to center of current user
|
||||||
|
if (role === Role.CENTER_OWNER) {
|
||||||
|
const center = await this.prisma.center.findUnique({
|
||||||
|
where: { centerOwnerId: ctx.http.me.id },
|
||||||
|
})
|
||||||
|
if (!center) {
|
||||||
|
throw new Error('Center not found')
|
||||||
|
}
|
||||||
|
args.filter = { centerId: { in: [center.id] } }
|
||||||
|
}
|
||||||
|
|
||||||
return await this.prisma.service.findMany({
|
return await this.prisma.service.findMany({
|
||||||
...query,
|
...query,
|
||||||
where: args.filter ?? undefined,
|
where: args.filter ?? undefined,
|
||||||
@@ -158,7 +206,7 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, _ctx, _info) => {
|
||||||
return await this.prisma.service.findUnique({
|
return await this.prisma.service.findUnique({
|
||||||
...query,
|
...query,
|
||||||
where: args.input,
|
where: args.input,
|
||||||
@@ -177,11 +225,16 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
type: this.service(),
|
type: this.service(),
|
||||||
args: {
|
args: {
|
||||||
input: t.arg({
|
input: t.arg({
|
||||||
type: this.builder.generator.getCreateInput('Service'),
|
type: this.builder.generator.getCreateInput('Service', ['user']),
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
|
if (ctx.isSubscription) {
|
||||||
|
throw new Error('Not allowed')
|
||||||
|
}
|
||||||
|
// replace userId with current user id
|
||||||
|
args.input.user = { connect: { id: ctx.http.me.id } }
|
||||||
return await this.prisma.service.create({
|
return await this.prisma.service.create({
|
||||||
...query,
|
...query,
|
||||||
data: args.input,
|
data: args.input,
|
||||||
@@ -201,7 +254,7 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, _ctx, _info) => {
|
||||||
return await this.prisma.service.update({
|
return await this.prisma.service.update({
|
||||||
...query,
|
...query,
|
||||||
where: args.where,
|
where: args.where,
|
||||||
@@ -218,7 +271,7 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, _ctx, _info) => {
|
||||||
return await this.prisma.service.delete({
|
return await this.prisma.service.delete({
|
||||||
...query,
|
...query,
|
||||||
where: args.where,
|
where: args.where,
|
||||||
@@ -242,7 +295,7 @@ export class ServiceSchema extends PothosSchema {
|
|||||||
required: false,
|
required: false,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, _root, args, ctx, _info) => {
|
||||||
if (ctx.isSubscription) {
|
if (ctx.isSubscription) {
|
||||||
throw new Error('Not allowed')
|
throw new Error('Not allowed')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user