feat: enhance CronService and OrderSchema with new scheduling and authorization features

- Removed unnecessary logging from CronService methods to streamline execution.
- Introduced a new cron job in CronService to check if all schedule dates are completed and update the schedule status accordingly.
- Added a new query in OrderSchema to retrieve completed orders for moderators, including authorization checks for user roles.
- Updated PersonalMilestoneSchema to allow for creating multiple personal milestones with necessary input fields.

These changes improve the scheduling logic and enhance the GraphQL API's authorization mechanisms, ensuring better user experience and state management.
This commit is contained in:
2024-12-13 20:14:18 +07:00
parent 0a1b42f908
commit b709bec583
3 changed files with 57 additions and 13 deletions

View File

@@ -16,7 +16,6 @@ export class CronService {
// cron every 1 minute to check schedule date status // cron every 1 minute to check schedule date status
@Cron(CronExpression.EVERY_MINUTE) @Cron(CronExpression.EVERY_MINUTE)
async checkScheduleDateStatus() { async checkScheduleDateStatus() {
Logger.log('Checking schedule date status', 'CronService')
const schedules = await this.prisma.scheduleDate.findMany({ const schedules = await this.prisma.scheduleDate.findMany({
where: { where: {
end: { end: {
@@ -48,13 +47,6 @@ export class CronService {
} }
} }
// if (collaborationSession.collaboratorsIds.length === 1) {
// return {
// id: schedule.id,
// status: ScheduleDateStatus.MISSING_CUSTOMER,
// }
// }
if (collaborationSession.collaboratorsIds.length === 2) { if (collaborationSession.collaboratorsIds.length === 2) {
return { return {
id: schedule.id, id: schedule.id,
@@ -74,10 +66,31 @@ export class CronService {
} }
} }
// cron every 10 seconds to check if all scheduledate in schedule has status complete then mark schedule as completed
@Cron(CronExpression.EVERY_10_SECONDS)
async checkScheduleCompleted() {
const schedules = await this.prisma.schedule.findMany({
where: {
status: ScheduleStatus.PUBLISHED,
},
})
for (const schedule of schedules) {
const scheduleDates = await this.prisma.scheduleDate.findMany({
where: { scheduleId: schedule.id },
})
if (scheduleDates.every((date) => date.status === ScheduleDateStatus.COMPLETED)) {
await this.prisma.schedule.update({
where: { id: schedule.id },
data: { status: ScheduleStatus.COMPLETED },
})
Logger.log(`Schedule ${schedule.id} has been completed`, 'CronService')
}
}
}
// cron every 1 minute to check payment status where created_at is more than 15 minutes // cron every 1 minute to check payment status where created_at is more than 15 minutes
@Cron(CronExpression.EVERY_MINUTE) @Cron(CronExpression.EVERY_MINUTE)
async checkPaymentStatus() { async checkPaymentStatus() {
Logger.log('Checking payment status', 'CronService')
const payments = await this.prisma.payment.findMany({ const payments = await this.prisma.payment.findMany({
where: { where: {
status: PaymentStatus.PENDING, status: PaymentStatus.PENDING,
@@ -102,7 +115,6 @@ export class CronService {
// cron every 1 minute to check if there is any schedule date start in less than 30 minutes // cron every 1 minute to check if there is any schedule date start in less than 30 minutes
@Cron(CronExpression.EVERY_MINUTE) @Cron(CronExpression.EVERY_MINUTE)
async taskCheckScheduleDateStart() { async taskCheckScheduleDateStart() {
Logger.log('Checking schedule date start', 'CronService')
const schedules = await this.prisma.schedule.findMany({ const schedules = await this.prisma.schedule.findMany({
where: { where: {
AND: [ AND: [
@@ -147,7 +159,6 @@ export class CronService {
// cron every day to disable service without any schedule in the past 30 days // cron every day to disable service without any schedule in the past 30 days
@Cron(CronExpression.EVERY_DAY_AT_1AM) @Cron(CronExpression.EVERY_DAY_AT_1AM)
async taskDisableServiceWithoutSchedule() { async taskDisableServiceWithoutSchedule() {
Logger.log('Disabling service without any schedule', 'CronService')
const services = await this.prisma.service.findMany({ const services = await this.prisma.service.findMany({
where: { where: {
NOT: { NOT: {

View File

@@ -1,5 +1,5 @@
import { Inject, Injectable, Logger } from '@nestjs/common' import { Inject, Injectable, Logger } from '@nestjs/common'
import { OrderStatus, 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 { Builder } from '../Graphql/graphql.builder' import { Builder } from '../Graphql/graphql.builder'
@@ -160,7 +160,40 @@ export class OrderSchema extends PothosSchema {
}) })
}, },
}), }),
completedOrdersForModerator: t.prismaField({
type: [this.order()],
description: 'Retrieve a list of completed orders for moderator',
args: this.builder.generator.findManyArgs('Order'),
resolve: async (query, _root, args, ctx, _info) => {
if (ctx.isSubscription) {
throw new Error('Orders cannot be retrieved in subscription context')
}
if (!ctx.http.me) {
throw new Error('Unauthorized')
}
// only for role moderator
if (ctx.http.me.role !== Role.MODERATOR) {
throw new Error('Unauthorized')
}
// return completed order list where schedule status is COMPLETED
return await this.prisma.order.findMany({
...query,
where: {
AND: [
...(args.filter ? [args.filter] : []),
{
status: OrderStatus.PAID,
schedule: {
status: ScheduleStatus.COMPLETED,
},
},
],
},
})
},
}),
})) }))
// mutation section // mutation section
this.builder.mutationFields((t) => ({ this.builder.mutationFields((t) => ({
createOrder: t.prismaField({ createOrder: t.prismaField({

View File

@@ -112,7 +112,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
required: true, required: true,
}), }),
data: t.arg({ data: t.arg({
type: [this.builder.generator.getCreateManyInput('PersonalMilestone')], type: [this.builder.generator.getCreateManyInput('PersonalMilestone', ['schedule', 'user'])],
description: 'The data for the personal milestone.', description: 'The data for the personal milestone.',
required: true, required: true,
}), }),