first commit

This commit is contained in:
2026-01-17 14:17:42 +05:30
commit 0f194eb9e7
328 changed files with 73544 additions and 0 deletions

371
lib/commission.ts Normal file
View File

@@ -0,0 +1,371 @@
import { prisma } from '@/lib/prisma'
interface CommissionResult {
success: boolean
message: string
commissions?: Array<{
referrerId: string
referrerName: string | null
amount: number
level: number
type: string
}>
error?: string
}
export async function calculateCommissions(orderId: string): Promise<CommissionResult> {
try {
// Get the order with user and referrer information
const order = await prisma.order.findUnique({
where: { id: orderId },
include: {
user: {
include: {
referrer: true
}
},
orderItems: {
include: {
product: true
}
}
}
})
if (!order || !order.user.referrerId) {
return { success: false, message: 'No referrer found for commission calculation' }
}
// Get commission settings
const commissionSettings = await prisma.commissionSettings.findMany({
where: { isActive: true },
orderBy: { level: 'asc' }
})
if (commissionSettings.length === 0) {
// Initialize default settings if none exist
await initializeCommissionSettings()
return await calculateCommissions(orderId) // Retry after initialization
}
const commissions = []
let currentUser: any = order.user
let level = 1
// Calculate commissions for each level (up to 3 levels for partners)
for (const setting of commissionSettings) {
if (!currentUser.referrerId || level > 3) break // Limit to 3 levels
// Get referrer with rank information
const referrer = await prisma.user.findUnique({
where: { id: currentUser.referrerId },
include: {
referrer: true,
currentRank: true
}
})
if (!referrer) break
// Only calculate commissions for MEMBER (partners) referrers
if (referrer.role !== 'MEMBER') {
currentUser = referrer
continue
}
// Calculate base commission amount
let commissionAmount = (order.total * setting.percentage) / 100
// Apply rank multiplier if available
if (referrer.currentRank) {
commissionAmount *= referrer.currentRank.commissionMultiplier
}
// Create commission record
await prisma.commission.create({
data: {
userId: referrer.id,
fromUserId: order.userId,
orderId: order.id,
amount: commissionAmount,
level: level,
type: level === 1 ? 'REFERRAL' : 'LEVEL',
status: 'APPROVED' // Auto-approve for partners
}
})
// Update referrer's wallet
await prisma.wallet.upsert({
where: { userId: referrer.id },
update: {
balance: { increment: commissionAmount },
totalEarnings: { increment: commissionAmount }
},
create: {
userId: referrer.id,
balance: commissionAmount,
totalEarnings: commissionAmount,
totalWithdrawn: 0
}
})
commissions.push({
referrerId: referrer.id,
referrerName: referrer.name,
amount: commissionAmount,
level: level,
type: level === 1 ? 'REFERRAL' : 'LEVEL'
})
console.log(`Level ${level} commission: ₹${commissionAmount} for partner ${referrer.name} (${referrer.email})`)
// Update currentUser to the referrer for next iteration
currentUser = referrer
level++
}
return {
success: true,
commissions,
message: `Generated ${commissions.length} commission(s)`
}
} catch (error) {
console.error('Error calculating commissions:', error)
return {
success: false,
message: 'Failed to calculate commissions',
error: error instanceof Error ? error.message : 'Unknown error'
}
}
}
export async function getCommissionSettings(): Promise<{
success: boolean
settings: any[]
}> {
try {
const settings = await prisma.commissionSettings.findMany({
where: { isActive: true },
orderBy: { level: 'asc' }
})
return { success: true, settings }
} catch (error) {
console.error('Error fetching commission settings:', error)
return { success: false, settings: [] }
}
}
export function calculateCommissionAmount(
orderTotal: number,
percentage: number,
rankMultiplier: number = 1
): number {
const baseCommission = (orderTotal * percentage) / 100
return baseCommission * rankMultiplier
}
export class CommissionService {
static async calculateCommissions(orderId: string): Promise<CommissionResult> {
return calculateCommissions(orderId)
}
static async getCommissionSettings(): Promise<{
success: boolean
settings: any[]
}> {
return getCommissionSettings()
}
static calculateCommissionAmount(
orderTotal: number,
percentage: number,
rankMultiplier: number = 1
): number {
return calculateCommissionAmount(orderTotal, percentage, rankMultiplier)
}
static async getUserCommissions(userId: string, limit: number = 10): Promise<{
success: boolean
commissions: any[]
}> {
try {
const commissions = await prisma.commission.findMany({
where: { userId },
include: {
fromUser: {
select: {
name: true,
email: true
}
}
},
orderBy: { createdAt: 'desc' },
take: limit
})
return { success: true, commissions }
} catch (error) {
console.error('Error fetching user commissions:', error)
return { success: false, commissions: [] }
}
}
static async getCommissionStats(userId: string): Promise<{
success: boolean
stats?: {
totalEarnings: number
pendingCommissions: number
thisMonthEarnings: number
}
error?: string
}> {
try {
const [totalEarnings, pendingCommissions, thisMonthEarnings] = await Promise.all([
prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] }
},
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: {
userId,
status: 'PENDING'
},
_sum: { amount: true }
}),
prisma.commission.aggregate({
where: {
userId,
status: { in: ['APPROVED', 'PAID'] },
createdAt: {
gte: new Date(new Date().getFullYear(), new Date().getMonth(), 1)
}
},
_sum: { amount: true }
})
])
return {
success: true,
stats: {
totalEarnings: totalEarnings._sum.amount || 0,
pendingCommissions: pendingCommissions._sum.amount || 0,
thisMonthEarnings: thisMonthEarnings._sum.amount || 0
}
}
} catch (error) {
console.error('Error fetching commission stats:', error)
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
}
}
}
static async getTeamStats(userId: string): Promise<{
success: boolean
stats?: {
directReferrals: number
totalTeamSize: number
teamSalesVolume: number
activeMembers: number
}
error?: string
}> {
try {
// Get direct referrals count
const directReferrals = await prisma.user.count({
where: { referrerId: userId }
})
// Get total team size (all levels)
const allReferrals = await this.getAllReferrals(userId)
const totalTeamSize = allReferrals.length
// Get team sales volume (last 30 days)
const thirtyDaysAgo = new Date()
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30)
const teamSalesResult = await prisma.order.aggregate({
where: {
userId: { in: allReferrals },
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] },
createdAt: { gte: thirtyDaysAgo }
},
_sum: { total: true }
})
// Get active team members (made purchase in last 30 days)
const activeMembers = await prisma.user.count({
where: {
id: { in: allReferrals },
orders: {
some: {
status: { in: ['PAID', 'SHIPPED', 'DELIVERED'] },
createdAt: { gte: thirtyDaysAgo }
}
}
}
})
return {
success: true,
stats: {
directReferrals,
totalTeamSize,
activeMembers,
teamSalesVolume: teamSalesResult._sum.total || 0
}
}
} catch (error) {
console.error('Error fetching team stats:', error)
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
}
}
}
private static async getAllReferrals(userId: string, visited = new Set<string>()): Promise<string[]> {
if (visited.has(userId)) return []
visited.add(userId)
const directReferrals = await prisma.user.findMany({
where: { referrerId: userId },
select: { id: true }
})
let allReferrals = directReferrals.map(r => r.id)
// Recursively get referrals of referrals
for (const referral of directReferrals) {
const subReferrals = await this.getAllReferrals(referral.id, visited)
allReferrals = [...allReferrals, ...subReferrals]
}
return allReferrals
}
}
// Initialize default commission settings for partners
export async function initializeCommissionSettings(): Promise<void> {
try {
const existingSettings = await prisma.commissionSettings.findMany()
if (existingSettings.length === 0) {
await prisma.commissionSettings.createMany({
data: [
{ level: 1, percentage: 5.0, isActive: true }, // 5% for direct referrer (partner)
{ level: 2, percentage: 2.0, isActive: true }, // 2% for level 2 partner
{ level: 3, percentage: 1.0, isActive: true }, // 1% for level 3 partner
]
})
console.log('Commission settings initialized for partner system')
}
} catch (error) {
console.error('Failed to initialize commission settings:', error)
}
}