188 lines
6.6 KiB
TypeScript
188 lines
6.6 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { withAdminAuth } from '@/lib/admin-middleware'
|
|
import { connectDB } from '@/lib/mongodb'
|
|
import { User } from '@/models/user'
|
|
import { Transaction } from '@/models/transaction'
|
|
import { Billing } from '@/models/billing'
|
|
import { DeveloperRequest } from '@/models/developer-request'
|
|
|
|
export async function GET(request: NextRequest) {
|
|
return withAdminAuth(request, async (req, admin) => {
|
|
try {
|
|
await connectDB()
|
|
|
|
const { searchParams } = new URL(request.url)
|
|
const reportType = searchParams.get('type')
|
|
const format = searchParams.get('format') || 'json'
|
|
const dateFrom = searchParams.get('dateFrom')
|
|
const dateTo = searchParams.get('dateTo')
|
|
|
|
// Build date filter
|
|
const dateFilter: any = {}
|
|
if (dateFrom || dateTo) {
|
|
dateFilter.createdAt = {}
|
|
if (dateFrom) dateFilter.createdAt.$gte = new Date(dateFrom)
|
|
if (dateTo) dateFilter.createdAt.$lte = new Date(dateTo)
|
|
}
|
|
|
|
let data: any = {}
|
|
|
|
switch (reportType) {
|
|
case 'users':
|
|
data = await User.find(dateFilter)
|
|
.select('-password -refreshToken')
|
|
.sort({ createdAt: -1 })
|
|
break
|
|
|
|
case 'transactions':
|
|
data = await Transaction.find(dateFilter)
|
|
.populate('userId', 'name email siliconId')
|
|
.sort({ createdAt: -1 })
|
|
break
|
|
|
|
case 'billing':
|
|
data = await Billing.find(
|
|
dateFilter.createdAt ? { created_at: dateFilter.createdAt } : {}
|
|
).sort({ created_at: -1 })
|
|
break
|
|
|
|
case 'developer-requests':
|
|
const devFilter = dateFilter.createdAt ? { createdAt: dateFilter.createdAt } : {}
|
|
data = await (DeveloperRequest as any)
|
|
.find(devFilter)
|
|
.populate('userId', 'name email siliconId')
|
|
.sort({ createdAt: -1 })
|
|
break
|
|
|
|
case 'summary':
|
|
// Generate comprehensive summary report
|
|
const [users, transactions, billings, developerRequests] = await Promise.all([
|
|
User.find(dateFilter).select('-password -refreshToken'),
|
|
Transaction.find(dateFilter).populate('userId', 'name email siliconId'),
|
|
Billing.find(dateFilter.createdAt ? { created_at: dateFilter.createdAt } : {}),
|
|
(DeveloperRequest as any)
|
|
.find(dateFilter.createdAt ? { createdAt: dateFilter.createdAt } : {})
|
|
.populate('userId', 'name email siliconId'),
|
|
])
|
|
|
|
// Calculate summary statistics
|
|
const userStats = {
|
|
total: users.length,
|
|
verified: users.filter((u) => u.isVerified).length,
|
|
admins: users.filter((u) => u.role === 'admin').length,
|
|
totalBalance: users.reduce((sum, u) => sum + (u.balance || 0), 0),
|
|
}
|
|
|
|
const transactionStats = {
|
|
total: transactions.length,
|
|
totalAmount: transactions.reduce((sum, t) => sum + t.amount, 0),
|
|
credits: transactions.filter((t) => t.type === 'credit').length,
|
|
debits: transactions.filter((t) => t.type === 'debit').length,
|
|
}
|
|
|
|
const billingStats = {
|
|
total: billings.length,
|
|
totalRevenue: billings.reduce((sum, b) => sum + b.amount, 0),
|
|
completed: billings.filter((b) => b.payment_status === 'paid').length,
|
|
pending: billings.filter((b) => b.payment_status === 'pending').length,
|
|
}
|
|
|
|
const developerStats = {
|
|
total: developerRequests.length,
|
|
pending: developerRequests.filter((d) => d.status === 'pending').length,
|
|
inProgress: developerRequests.filter((d) => d.status === 'in_progress').length,
|
|
completed: developerRequests.filter((d) => d.status === 'completed').length,
|
|
}
|
|
|
|
data = {
|
|
summary: {
|
|
users: userStats,
|
|
transactions: transactionStats,
|
|
billing: billingStats,
|
|
developerRequests: developerStats,
|
|
},
|
|
users: users.slice(0, 100), // Limit for performance
|
|
transactions: transactions.slice(0, 100),
|
|
billings: billings.slice(0, 100),
|
|
developerRequests: developerRequests.slice(0, 100),
|
|
}
|
|
break
|
|
|
|
default:
|
|
return NextResponse.json({ error: 'Invalid report type' }, { status: 400 })
|
|
}
|
|
|
|
if (format === 'csv') {
|
|
// Convert to CSV format
|
|
const csv = convertToCSV(data, reportType)
|
|
|
|
return new NextResponse(csv, {
|
|
headers: {
|
|
'Content-Type': 'text/csv',
|
|
'Content-Disposition': `attachment; filename="${reportType}_report_${new Date().toISOString().split('T')[0]}.csv"`,
|
|
},
|
|
})
|
|
}
|
|
|
|
return NextResponse.json({
|
|
reportType,
|
|
generatedAt: new Date().toISOString(),
|
|
generatedBy: admin.name,
|
|
dateRange: { from: dateFrom, to: dateTo },
|
|
data,
|
|
})
|
|
} catch (error) {
|
|
console.error('Admin reports error:', error)
|
|
return NextResponse.json({ error: 'Failed to generate report' }, { status: 500 })
|
|
}
|
|
})
|
|
}
|
|
|
|
function convertToCSV(data: any, reportType: string): string {
|
|
if (!Array.isArray(data)) {
|
|
if (reportType === 'summary' && data.summary) {
|
|
// For summary reports, create a simple CSV with key metrics
|
|
const lines = [
|
|
'Metric,Value',
|
|
`Total Users,${data.summary.users.total}`,
|
|
`Verified Users,${data.summary.users.verified}`,
|
|
`Admin Users,${data.summary.users.admins}`,
|
|
`Total Balance,${data.summary.users.totalBalance}`,
|
|
`Total Transactions,${data.summary.transactions.total}`,
|
|
`Transaction Amount,${data.summary.transactions.totalAmount}`,
|
|
`Total Billing Records,${data.summary.billing.total}`,
|
|
`Total Revenue,${data.summary.billing.totalRevenue}`,
|
|
`Developer Requests,${data.summary.developerRequests.total}`,
|
|
]
|
|
return lines.join('\n')
|
|
}
|
|
return 'No data available'
|
|
}
|
|
|
|
if (data.length === 0) {
|
|
return 'No data available'
|
|
}
|
|
|
|
// Get headers from first object
|
|
const headers = Object.keys(data[0]).filter(
|
|
(key) => typeof data[0][key] !== 'object' || data[0][key] === null
|
|
)
|
|
|
|
// Create CSV content
|
|
const csvHeaders = headers.join(',')
|
|
const csvRows = data.map((row) =>
|
|
headers
|
|
.map((header) => {
|
|
const value = row[header]
|
|
if (value === null || value === undefined) return ''
|
|
if (typeof value === 'string' && value.includes(',')) {
|
|
return `"${value.replace(/"/g, '""')}"`
|
|
}
|
|
return value
|
|
})
|
|
.join(',')
|
|
)
|
|
|
|
return [csvHeaders, ...csvRows].join('\n')
|
|
}
|