diff --git a/src/Analytic/analytic.schema.ts b/src/Analytic/analytic.schema.ts index 453581f..a1bb34e 100644 --- a/src/Analytic/analytic.schema.ts +++ b/src/Analytic/analytic.schema.ts @@ -1,11 +1,6 @@ import { Inject, Injectable } from '@nestjs/common' import { OrderStatus, Prisma, Role, ServiceStatus } from '@prisma/client' -import { - Pothos, - PothosRef, - PothosSchema, - SchemaBuilderToken, -} from '@smatch-corp/nestjs-pothos' +import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos' import { DateTimeUtils } from 'src/common/utils/datetime.utils' import { Builder } from 'src/Graphql/graphql.builder' import { PrismaService } from 'src/Prisma/prisma.service' @@ -125,6 +120,12 @@ export class AnalyticSchema extends PothosSchema { totalMentorCount: t.int({ description: 'The total number of mentors.', }), + totalServiceCount: t.int({ + description: 'The total number of services.', + }), + totalWorkshopCount: t.int({ + description: 'The total number of workshops.', + }), revenue: t.int({ description: 'The total revenue.', }), @@ -172,8 +173,7 @@ export class AnalyticSchema extends PothosSchema { resolve: async (_parent, _args, ctx, _info) => { if (ctx.isSubscription) throw new Error('Not allowed') if (!ctx.http.me) throw new Error('Unauthorized') - if (ctx.http.me.role !== Role.CUSTOMER) - throw new Error('Only customers can access this data') + if (ctx.http.me.role !== Role.CUSTOMER) throw new Error('Only customers can access this data') // calculate analytic const activeServiceCount = await this.prisma.order.count({ where: { @@ -219,8 +219,7 @@ export class AnalyticSchema extends PothosSchema { resolve: async (_parent, _args, ctx, _info) => { if (ctx.isSubscription) throw new Error('Not allowed') if (!ctx.http.me) throw new Error('Unauthorized') - if (ctx.http.me.role !== Role.CENTER_MENTOR) - throw new Error('Only center mentors can access this data') + if (ctx.http.me.role !== Role.CENTER_MENTOR) throw new Error('Only center mentors can access this data') // calculate analytic return { userId: ctx.http.me.id, @@ -233,8 +232,7 @@ export class AnalyticSchema extends PothosSchema { resolve: async (_parent, _args, ctx, _info) => { if (ctx.isSubscription) throw new Error('Not allowed') if (!ctx.http.me) throw new Error('Unauthorized') - if (ctx.http.me.role !== Role.CENTER_OWNER) - throw new Error('Only center owners can access this data') + if (ctx.http.me.role !== Role.CENTER_OWNER) throw new Error('Only center owners can access this data') // get center by owner id const center = await this.prisma.center.findUnique({ where: { @@ -281,8 +279,7 @@ export class AnalyticSchema extends PothosSchema { }) if (!service) continue const commission = service.commission - const actualRevenue = - (order.total || 0) - (order.total || 0) * commission + const actualRevenue = (order.total || 0) - (order.total || 0) * commission revenue += actualRevenue } return { @@ -323,10 +320,7 @@ export class AnalyticSchema extends PothosSchema { resolve: async (_parent, args, ctx, _info) => { if (ctx.isSubscription) throw new Error('Not allowed') if (!ctx.http.me) throw new Error('Unauthorized') - if ( - ctx.http.me.role !== Role.ADMIN && - ctx.http.me.role !== Role.MODERATOR - ) + if (ctx.http.me.role !== Role.ADMIN && ctx.http.me.role !== Role.MODERATOR) throw new Error('Only admins and moderators can access this data') // calculate analytic for services sorted by args.serviceSortBy and args.timeframes const topServices = await this.prisma.service.findMany({ @@ -411,13 +405,17 @@ export class AnalyticSchema extends PothosSchema { status: ServiceStatus.REJECTED, }, }) + // get total workshop count + const totalWorkshopCount = await this.prisma.workshop.count() + // get total order count + const totalOrderCount = await this.prisma.order.count() + // get total service count + const totalServiceCount = await this.prisma.service.count() // get revenue let revenue = 0 // query all orders of services in all centers in the past args.timeframes and calculate actual revenue of each order by convert commission percentage to float // convert args.timeframes to number of days - const timeframes = DateTimeUtils.subtractDaysFromTimeframe( - args.timeframes, - ) + const timeframes = DateTimeUtils.subtractDaysFromTimeframe(args.timeframes) const orders = await this.prisma.order.findMany({ where: { status: OrderStatus.PAID, @@ -432,8 +430,7 @@ export class AnalyticSchema extends PothosSchema { }) if (!service) continue const commission = service.commission - const actualRevenue = - (order.total || 0) - (order.total || 0) * commission + const actualRevenue = (order.total || 0) - (order.total || 0) * commission revenue += actualRevenue } // return analytic @@ -449,6 +446,9 @@ export class AnalyticSchema extends PothosSchema { revenue: revenue, approvedServiceCount: approvedServiceCount, rejectedServiceCount: rejectedServiceCount, + totalWorkshopCount: totalWorkshopCount, + totalOrderCount: totalOrderCount, + totalServiceCount: totalServiceCount, updatedAt: DateTimeUtils.now(), } }, diff --git a/src/Document/document.event.ts b/src/Document/document.event.ts index a30af5e..22de7ab 100644 --- a/src/Document/document.event.ts +++ b/src/Document/document.event.ts @@ -5,4 +5,5 @@ export enum DocumentEvent { PAGE_CREATED = 'document_page_created', PAGE_DELETED = 'document_page_deleted', ACTIVE_DOCUMENT_ID_CHANGED = 'document_active_document_id_changed', + REQUEST_SYNC = 'document_request_sync', } diff --git a/src/Document/document.schema.ts b/src/Document/document.schema.ts index 057e0c3..96d6b73 100644 --- a/src/Document/document.schema.ts +++ b/src/Document/document.schema.ts @@ -204,7 +204,7 @@ export class DocumentSchema extends PothosSchema { }, }), - eventUpdateDocument: t.field({ + eventDocumentChanged: t.field({ type: this.documentDelta(), args: { data: t.arg({ @@ -226,6 +226,23 @@ export class DocumentSchema extends PothosSchema { return args.data }, }), + eventDocumentRequestSync: t.field({ + type: this.documentDelta(), + args: { + data: t.arg({ + type: this.documentDeltaInput(), + required: true, + }), + }, + resolve: async (_, args, ctx: SchemaContext) => { + if (ctx.isSubscription) throw new Error('Not allowed') + return { + ...args.data, + senderId: ctx.http?.me?.id, + eventType: DocumentEvent.REQUEST_SYNC, + } + }, + }), updateDocument: t.prismaField({ type: this.document(), diff --git a/src/RefundTicket/refundticket.schema.ts b/src/RefundTicket/refundticket.schema.ts index 6937ae9..8cfdf42 100644 --- a/src/RefundTicket/refundticket.schema.ts +++ b/src/RefundTicket/refundticket.schema.ts @@ -3,6 +3,7 @@ import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-cor import { Builder } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' import { OrderStatus, PaymentStatus, RefundTicketStatus, Role } from '@prisma/client' +import { DateTimeUtils } from 'src/common/utils/datetime.utils' @Injectable() export class RefundTicketSchema extends PothosSchema { @@ -107,12 +108,20 @@ export class RefundTicketSchema extends PothosSchema { if (!order.total || order.total === 0) { throw new Error('Order total is null or free') } + // calculate refund amount based on order time: if order is less than 24 hours, refund 100%, if more than 24 hours, less than 48 hours, refund 50%, if more than 72 hours, cannot refund + const now = DateTimeUtils.now() + const orderDate = DateTimeUtils.fromDate(order.createdAt) + const diffTime = Math.abs(now.diff(orderDate).toMillis()) + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + let refundAmount = 0 + if (diffDays < 24) refundAmount = order.total + else if (diffDays < 48) refundAmount = order.total * 0.5 // create refund ticket const refundTicket = await this.prisma.refundTicket.create({ data: { orderId: order.id, status: RefundTicketStatus.PENDING, - amount: order.total, + amount: refundAmount, }, }) return refundTicket