201 lines
6.1 KiB
TypeScript
201 lines
6.1 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { withAdminAuth } from '@/lib/admin-middleware'
|
|
import { connectDB } from '@/lib/mongodb'
|
|
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 page = parseInt(searchParams.get('page') || '1')
|
|
const limit = parseInt(searchParams.get('limit') || '20')
|
|
const serviceType = searchParams.get('serviceType') || ''
|
|
const status = searchParams.get('status') || ''
|
|
const dateFrom = searchParams.get('dateFrom')
|
|
const dateTo = searchParams.get('dateTo')
|
|
|
|
const skip = (page - 1) * limit
|
|
|
|
// Build filter query for billing services
|
|
const billingFilter: any = {}
|
|
|
|
if (serviceType && serviceType !== 'all') {
|
|
billingFilter.service_type = serviceType
|
|
}
|
|
|
|
if (status && status !== 'all') {
|
|
billingFilter.service_status = status
|
|
}
|
|
|
|
if (dateFrom || dateTo) {
|
|
billingFilter.created_at = {}
|
|
if (dateFrom) billingFilter.created_at.$gte = new Date(dateFrom)
|
|
if (dateTo) billingFilter.created_at.$lte = new Date(dateTo)
|
|
}
|
|
|
|
// Fetch billing services
|
|
const [billingServices, totalBillingServices] = await Promise.all([
|
|
Billing.find(billingFilter).sort({ created_at: -1 }).skip(skip).limit(limit),
|
|
Billing.countDocuments(billingFilter),
|
|
])
|
|
|
|
// Build filter for developer requests
|
|
const devRequestFilter: any = {}
|
|
|
|
if (status && status !== 'all') {
|
|
devRequestFilter.status = status
|
|
}
|
|
|
|
if (dateFrom || dateTo) {
|
|
devRequestFilter.createdAt = {}
|
|
if (dateFrom) devRequestFilter.createdAt.$gte = new Date(dateFrom)
|
|
if (dateTo) devRequestFilter.createdAt.$lte = new Date(dateTo)
|
|
}
|
|
|
|
// Fetch developer requests
|
|
const [developerRequests, totalDeveloperRequests] = await Promise.all([
|
|
(DeveloperRequest as any)
|
|
.find(devRequestFilter)
|
|
.populate('userId', 'name email siliconId')
|
|
.sort({ createdAt: -1 })
|
|
.skip(skip)
|
|
.limit(limit),
|
|
(DeveloperRequest as any).countDocuments(devRequestFilter),
|
|
])
|
|
|
|
// Service statistics
|
|
const serviceStats = await Billing.aggregate([
|
|
{
|
|
$group: {
|
|
_id: '$service_type',
|
|
count: { $sum: 1 },
|
|
revenue: { $sum: '$amount' },
|
|
activeServices: {
|
|
$sum: { $cond: [{ $eq: ['$service_status', 'active'] }, 1, 0] },
|
|
},
|
|
},
|
|
},
|
|
{ $sort: { count: -1 } },
|
|
])
|
|
|
|
// Status breakdown
|
|
const statusBreakdown = await Billing.aggregate([
|
|
{
|
|
$group: {
|
|
_id: '$service_status',
|
|
count: { $sum: 1 },
|
|
},
|
|
},
|
|
])
|
|
|
|
const totalPages = Math.ceil(Math.max(totalBillingServices, totalDeveloperRequests) / limit)
|
|
|
|
return NextResponse.json({
|
|
billingServices,
|
|
developerRequests,
|
|
serviceStats,
|
|
statusBreakdown,
|
|
pagination: {
|
|
currentPage: page,
|
|
totalPages,
|
|
totalBillingServices,
|
|
totalDeveloperRequests,
|
|
hasNext: page < totalPages,
|
|
hasPrev: page > 1,
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error('Admin services fetch error:', error)
|
|
return NextResponse.json({ error: 'Failed to fetch services data' }, { status: 500 })
|
|
}
|
|
})
|
|
}
|
|
|
|
export async function POST(request: NextRequest) {
|
|
return withAdminAuth(request, async (req, admin) => {
|
|
try {
|
|
await connectDB()
|
|
|
|
const body = await request.json()
|
|
const { action, serviceId, serviceType, data } = body
|
|
|
|
if (action === 'updateBilling') {
|
|
const billing = await Billing.findByIdAndUpdate(
|
|
serviceId,
|
|
{
|
|
service_status: data.service_status,
|
|
updated_at: new Date(),
|
|
},
|
|
{ new: true }
|
|
)
|
|
|
|
if (!billing) {
|
|
return NextResponse.json({ error: 'Service not found' }, { status: 404 })
|
|
}
|
|
|
|
return NextResponse.json({ service: billing })
|
|
}
|
|
|
|
if (action === 'updateDeveloperRequest') {
|
|
const developerRequest = await (DeveloperRequest as any)
|
|
.findByIdAndUpdate(
|
|
serviceId,
|
|
{
|
|
status: data.status,
|
|
assignedDeveloper: data.assignedDeveloper,
|
|
estimatedCompletionDate: data.estimatedCompletionDate,
|
|
notes: data.notes,
|
|
updatedAt: new Date(),
|
|
},
|
|
{ new: true }
|
|
)
|
|
.populate('userId', 'name email siliconId')
|
|
|
|
if (!developerRequest) {
|
|
return NextResponse.json({ error: 'Developer request not found' }, { status: 404 })
|
|
}
|
|
|
|
return NextResponse.json({ service: developerRequest })
|
|
}
|
|
|
|
if (action === 'cancelService') {
|
|
if (serviceType === 'billing') {
|
|
const billing = await Billing.findByIdAndUpdate(
|
|
serviceId,
|
|
{
|
|
service_status: 'cancelled',
|
|
updated_at: new Date(),
|
|
},
|
|
{ new: true }
|
|
)
|
|
|
|
return NextResponse.json({ service: billing })
|
|
}
|
|
|
|
if (serviceType === 'developer') {
|
|
const updatedDeveloperRequest = await (DeveloperRequest as any)
|
|
.findByIdAndUpdate(
|
|
serviceId,
|
|
{
|
|
status: 'cancelled',
|
|
updatedAt: new Date(),
|
|
},
|
|
{ new: true }
|
|
)
|
|
.populate('userId', 'name email siliconId')
|
|
|
|
return NextResponse.json({ service: updatedDeveloperRequest })
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({ error: 'Invalid action or service type' }, { status: 400 })
|
|
} catch (error) {
|
|
console.error('Admin service action error:', error)
|
|
return NextResponse.json({ error: 'Failed to perform service action' }, { status: 500 })
|
|
}
|
|
})
|
|
}
|