80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Param,
|
|
Body,
|
|
Logger,
|
|
NotFoundException,
|
|
} from '@nestjs/common'
|
|
import { InjectRepository } from '@nestjs/typeorm'
|
|
import { Repository } from 'typeorm'
|
|
|
|
import { SubscriptionEntity } from '@/src/entities/subscription.entity'
|
|
import { SubscriptionStatus } from '@/providers/subscription.types'
|
|
|
|
/**
|
|
* Admin Subscriptions Controller
|
|
*
|
|
* Administrative endpoints for managing platform subscriptions.
|
|
* Matches frontend adminSubscriptionsApi contract.
|
|
*
|
|
* Routes:
|
|
* - GET /admin/subscriptions — list all subscriptions
|
|
* - POST /admin/subscriptions/:id/cancel — admin force-cancel
|
|
*/
|
|
@Controller('admin/subscriptions')
|
|
export class AdminSubscriptionsController {
|
|
private readonly logger = new Logger(AdminSubscriptionsController.name)
|
|
|
|
constructor(
|
|
@InjectRepository(SubscriptionEntity)
|
|
private readonly subscriptionRepository: Repository<SubscriptionEntity>,
|
|
) {}
|
|
|
|
/**
|
|
* GET /admin/subscriptions
|
|
*
|
|
* List all subscriptions with most recent first.
|
|
*/
|
|
@Get()
|
|
async list() {
|
|
const subscriptions = await this.subscriptionRepository.find({
|
|
order: { createdAt: 'DESC' },
|
|
})
|
|
return subscriptions
|
|
}
|
|
|
|
/**
|
|
* POST /admin/subscriptions/:id/cancel
|
|
*
|
|
* Admin force-cancel a subscription.
|
|
* Sets status to CANCELLED and records the cancellation timestamp.
|
|
*/
|
|
@Post(':id/cancel')
|
|
async cancel(
|
|
@Param('id') id: string,
|
|
@Body() body: { reason?: string },
|
|
) {
|
|
const subscription = await this.subscriptionRepository.findOne({ where: { id } })
|
|
|
|
if (!subscription) {
|
|
throw new NotFoundException(`Subscription ${id} not found`)
|
|
}
|
|
|
|
subscription.status = SubscriptionStatus.CANCELLED
|
|
subscription.cancelledAt = new Date()
|
|
subscription.cancelAtPeriodEnd = false
|
|
subscription.metadata = {
|
|
...subscription.metadata,
|
|
adminCancelReason: body.reason || 'admin_force_cancel',
|
|
adminCancelledAt: new Date().toISOString(),
|
|
}
|
|
|
|
const updated = await this.subscriptionRepository.save(subscription)
|
|
|
|
this.logger.log(`Admin cancelled subscription ${id}, reason: ${body.reason || 'none provided'}`)
|
|
|
|
return updated
|
|
}
|
|
}
|