refactor: enhance refund ticket logic and role-based access control
- Updated the RefundTicket schema to allow both customers and center mentors to request refunds, improving flexibility in refund processing. - Refined bank detail checks to differentiate between customers and center mentors, ensuring appropriate handling of bank information. - Implemented special handling for center mentors to always allow full refunds, enhancing user experience. - Improved error messages and validation checks throughout the refund process for better clarity and user guidance.
This commit is contained in:
@@ -212,7 +212,6 @@ export class QuizSchema extends PothosSchema {
|
|||||||
'centerMentorId',
|
'centerMentorId',
|
||||||
'createdAt',
|
'createdAt',
|
||||||
'updatedAt',
|
'updatedAt',
|
||||||
'service',
|
|
||||||
]),
|
]),
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -122,14 +122,20 @@ export class RefundTicketSchema extends PothosSchema {
|
|||||||
if (ctx.isSubscription) {
|
if (ctx.isSubscription) {
|
||||||
throw new Error('Subscription is not allowed')
|
throw new Error('Subscription is not allowed')
|
||||||
}
|
}
|
||||||
if (ctx.http.me?.role !== Role.CUSTOMER) {
|
|
||||||
throw new Error('Only customers can request refund')
|
// Check if the user is a customer or a center mentor
|
||||||
|
if (ctx.http.me?.role !== Role.CUSTOMER && ctx.http.me?.role !== Role.CENTER_MENTOR) {
|
||||||
|
throw new Error('Only customers and center mentors can request refund')
|
||||||
}
|
}
|
||||||
// check if bank bin and bank account number is exists else throw error
|
|
||||||
|
// Check bank details for non-center mentors
|
||||||
|
if (ctx.http.me?.role !== Role.CENTER_MENTOR) {
|
||||||
if (!ctx.http.me?.bankBin || !ctx.http.me?.bankAccountNumber) {
|
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')
|
throw new Error('Bank bin and bank account number are required, please update your profile first')
|
||||||
}
|
}
|
||||||
// check if order exists
|
}
|
||||||
|
|
||||||
|
// Check if order exists
|
||||||
const order = await this.prisma.order.findUnique({
|
const order = await this.prisma.order.findUnique({
|
||||||
where: { id: args.orderId },
|
where: { id: args.orderId },
|
||||||
include: {
|
include: {
|
||||||
@@ -139,49 +145,78 @@ export class RefundTicketSchema extends PothosSchema {
|
|||||||
if (!order) {
|
if (!order) {
|
||||||
throw new Error('Order not found')
|
throw new Error('Order not found')
|
||||||
}
|
}
|
||||||
// check if order status is PAID
|
|
||||||
|
// Check if order status is PAID
|
||||||
if (order.status !== OrderStatus.PAID) {
|
if (order.status !== OrderStatus.PAID) {
|
||||||
throw new Error('Order is not paid')
|
throw new Error('Order is not paid')
|
||||||
}
|
}
|
||||||
// check if order total is not null
|
|
||||||
|
// Check if order total is not null
|
||||||
if (!order.total || order.total === 0) {
|
if (!order.total || order.total === 0) {
|
||||||
throw new Error('Order total is null or free')
|
throw new Error('Order total is null or free')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order.refundTicket) {
|
if (order.refundTicket) {
|
||||||
throw new Error('Refund ticket already exists')
|
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
|
|
||||||
|
// Calculate refund amount based on order time
|
||||||
const now = DateTimeUtils.now()
|
const now = DateTimeUtils.now()
|
||||||
const orderDate = DateTimeUtils.fromDate(order.createdAt)
|
const orderDate = DateTimeUtils.fromDate(order.createdAt)
|
||||||
const diffTime = Math.abs(now.diff(orderDate).toMillis())
|
const diffTime = Math.abs(now.diff(orderDate).toMillis())
|
||||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
|
||||||
|
|
||||||
let refundAmount = 0
|
let refundAmount = 0
|
||||||
|
|
||||||
|
// Special handling for center mentors - full refund always allowed
|
||||||
|
if (ctx.http.me?.role === Role.CENTER_MENTOR) {
|
||||||
|
refundAmount = order.total
|
||||||
|
} else {
|
||||||
|
// Existing refund logic for customers
|
||||||
if (diffDays < 1) {
|
if (diffDays < 1) {
|
||||||
refundAmount = order.total
|
refundAmount = order.total
|
||||||
} else if (diffDays < 3) {
|
} else if (diffDays < 3) {
|
||||||
refundAmount = order.total * 0.5
|
refundAmount = order.total * 0.5
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (refundAmount === 0) {
|
if (refundAmount === 0) {
|
||||||
throw new Error('Cannot refund after 3 days')
|
throw new Error('Cannot refund after 3 days')
|
||||||
}
|
}
|
||||||
// create refund ticket
|
|
||||||
// get bank name from bank bin from banks.json
|
// Prepare bank details
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
let bankBin = ctx.http.me?.bankBin
|
||||||
const bank = banks.data.find((bank: any) => bank.bin === ctx.http.me?.bankBin)
|
let bankAccountNumber = ctx.http.me?.bankAccountNumber
|
||||||
|
let bankName = ''
|
||||||
|
|
||||||
|
// For center mentors, use a default or system bank account
|
||||||
|
if (ctx.http.me?.role === Role.CENTER_MENTOR) {
|
||||||
|
// You might want to replace this with a specific system bank account
|
||||||
|
bankBin = 'SYSTEM_MENTOR_REFUND'
|
||||||
|
bankAccountNumber = 'SYSTEM_MENTOR_ACCOUNT'
|
||||||
|
bankName = 'Center Mentor Refund Account'
|
||||||
|
} else {
|
||||||
|
// Existing bank lookup for customers
|
||||||
|
const bank = banks.data.find((bank: any) => bank.bin === bankBin)
|
||||||
if (!bank) {
|
if (!bank) {
|
||||||
throw new Error('Bank not found')
|
throw new Error('Bank not found')
|
||||||
}
|
}
|
||||||
|
bankName = bank.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create refund ticket
|
||||||
const refundTicket = await this.prisma.refundTicket.create({
|
const refundTicket = await this.prisma.refundTicket.create({
|
||||||
data: {
|
data: {
|
||||||
orderId: order.id,
|
orderId: order.id,
|
||||||
status: RefundTicketStatus.PENDING,
|
status: RefundTicketStatus.PENDING,
|
||||||
amount: refundAmount,
|
amount: refundAmount,
|
||||||
reason: args.reason,
|
reason: args.reason,
|
||||||
bankBin: ctx.http.me?.bankBin,
|
bankBin: bankBin,
|
||||||
bankAccountNumber: ctx.http.me?.bankAccountNumber,
|
bankAccountNumber: bankAccountNumber,
|
||||||
bankName: bank.name,
|
bankName: bankName,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return refundTicket
|
return refundTicket
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user