Update RefundTicketSchema to include additional fields for bank details and refund reasons; modify refund logic to enhance validation and error handling. Update TypeScript configuration to resolve JSON modules and bump subproject commit reference in epess-database.

This commit is contained in:
2024-11-26 23:55:39 +07:00
parent c9f03f251d
commit 01aede0b09
5 changed files with 955 additions and 12 deletions

View File

@@ -4,7 +4,7 @@ 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'
import * as banks from '../common/utils/banks.json'
@Injectable()
export class RefundTicketSchema extends PothosSchema {
constructor(
@@ -29,6 +29,21 @@ export class RefundTicketSchema extends PothosSchema {
type: RefundTicketStatus,
description: 'The status of the refund ticket.',
}),
bankBin: t.exposeString('bankBin', {
description: 'The bank BIN of the refund ticket.',
}),
bankAccountNumber: t.exposeString('bankAccountNumber', {
description: 'The bank account number of the refund ticket.',
}),
bankName: t.exposeString('bankName', {
description: 'The bank name of the refund ticket.',
}),
reason: t.exposeString('reason', {
description: 'The reason for the refund ticket.',
}),
moderator: t.relation('moderator', {
description: 'The moderator who processed the refund ticket.',
}),
createdAt: t.expose('createdAt', {
type: 'DateTime',
description: 'The date and time the refund ticket was created.',
@@ -99,7 +114,8 @@ export class RefundTicketSchema extends PothosSchema {
}),
reason: t.arg({
type: 'String',
required: true,
description: 'The reason for the refund, required if the refund is rejected',
required: false,
}),
},
resolve: async (_query, _root, args, ctx, _info) => {
@@ -109,9 +125,16 @@ export class RefundTicketSchema extends PothosSchema {
if (ctx.http.me?.role !== Role.CUSTOMER) {
throw new Error('Only customers can request refund')
}
// check if bank bin and bank account number is exists else throw error
if (!ctx.http.me?.bankBin || !ctx.http.me?.bankAccountNumber) {
throw new Error('Bank bin and bank account number are required, please update your profile first')
}
// check if order exists
const order = await this.prisma.order.findUnique({
where: { id: args.orderId },
include: {
refundTicket: true,
},
})
if (!order) {
throw new Error('Order not found')
@@ -124,21 +147,32 @@ export class RefundTicketSchema extends PothosSchema {
if (!order.total || order.total === 0) {
throw new Error('Order total is null or free')
}
if (order.refundTicket) {
throw new Error('Refund ticket already exists')
}
// 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
if (refundAmount === 0) throw new Error('Cannot refund after 72 hours')
if (diffDays < 1) refundAmount = order.total
else if (diffDays < 3) refundAmount = order.total * 0.5
if (refundAmount === 0) throw new Error('Cannot refund after 3 days')
// create refund ticket
// get bank name from bank bin from banks.json
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
const bank = banks.data.find((bank: any) => bank.bin === ctx.http.me?.bankBin)
if (!bank) throw new Error('Bank not found')
const refundTicket = await this.prisma.refundTicket.create({
data: {
orderId: order.id,
status: RefundTicketStatus.PENDING,
amount: refundAmount,
reason: args.reason,
bankBin: ctx.http.me?.bankBin,
bankAccountNumber: ctx.http.me?.bankAccountNumber,
bankName: bank.name,
},
})
return refundTicket
@@ -156,6 +190,10 @@ export class RefundTicketSchema extends PothosSchema {
type: this.refundTicketAction(),
required: true,
}),
reason: t.arg({
type: 'String',
required: false,
}),
},
resolve: async (_query, _root, args, ctx, _info) => {
if (ctx.isSubscription) {
@@ -164,10 +202,18 @@ export class RefundTicketSchema extends PothosSchema {
if (ctx.http.me?.role !== Role.MODERATOR) {
throw new Error('Only moderators can process refund tickets')
}
// if action is REJECT, reason is required
if (args.action === 'REJECT' && !args.reason) {
throw new Error('Reason is required when rejecting a refund ticket')
}
// update refund ticket status
const refundTicket = await this.prisma.refundTicket.update({
where: { id: args.refundTicketId },
data: { status: args.action === 'APPROVE' ? RefundTicketStatus.APPROVED : RefundTicketStatus.REJECTED },
data: {
status: args.action === 'APPROVE' ? RefundTicketStatus.APPROVED : RefundTicketStatus.REJECTED,
reason: args.action === 'REJECT' ? args.reason : undefined,
moderatorId: ctx.http.me?.id,
},
})
return refundTicket
},