miinventario-v2/apps/backend/src/modules/admin/admin.controller.ts
rckrdmrd 1a53b5c4d3 [MIINVENTARIO] feat: Initial commit - Sistema de inventario con análisis de video IA
- Backend NestJS con módulos de autenticación, inventario, créditos
- Frontend React con dashboard y componentes UI
- Base de datos PostgreSQL con migraciones
- Tests E2E configurados
- Configuración de Docker y deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 02:25:48 -06:00

249 lines
7.3 KiB
TypeScript

import {
Controller,
Get,
Post,
Patch,
Body,
Param,
Query,
UseGuards,
Req,
ParseUUIDPipe,
} from '@nestjs/common';
import { Request } from 'express';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { Roles } from '../../common/decorators/roles.decorator';
import { UserRole } from '../users/entities/user.entity';
import { AdminDashboardService } from './services/admin-dashboard.service';
import { AdminProvidersService } from './services/admin-providers.service';
import { AdminPackagesService } from './services/admin-packages.service';
import { AdminPromotionsService } from './services/admin-promotions.service';
import { AdminModerationService } from './services/admin-moderation.service';
import { DashboardQueryDto, DashboardPeriod } from './dto/dashboard.dto';
import { UpdateProviderDto } from './dto/provider.dto';
import { CreatePackageDto, UpdatePackageDto } from './dto/package.dto';
import { CreatePromotionDto, UpdatePromotionDto, ValidatePromoCodeDto } from './dto/promotion.dto';
import { ApproveProductDto, RejectProductDto, ApproveReferralDto, RejectReferralDto } from './dto/moderation.dto';
interface AuthRequest extends Request {
user: { id: string; role: string };
}
@Controller('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
export class AdminController {
constructor(
private readonly dashboardService: AdminDashboardService,
private readonly providersService: AdminProvidersService,
private readonly packagesService: AdminPackagesService,
private readonly promotionsService: AdminPromotionsService,
private readonly moderationService: AdminModerationService,
) {}
// Dashboard Endpoints
@Get('dashboard')
@Roles(UserRole.VIEWER)
async getDashboard(@Query() query: DashboardQueryDto) {
const startDate = query.startDate ? new Date(query.startDate) : undefined;
const endDate = query.endDate ? new Date(query.endDate) : undefined;
const metrics = await this.dashboardService.getDashboardMetrics(startDate, endDate);
return { metrics };
}
@Get('dashboard/revenue-series')
@Roles(UserRole.ADMIN)
async getRevenueSeries(@Query() query: DashboardQueryDto) {
const now = new Date();
const startDate = query.startDate
? new Date(query.startDate)
: new Date(now.getFullYear(), now.getMonth() - 1, 1);
const endDate = query.endDate ? new Date(query.endDate) : now;
const period = query.period || DashboardPeriod.DAY;
const series = await this.dashboardService.getRevenueSeries(startDate, endDate, period);
return { series };
}
// IA Providers Endpoints
@Get('providers')
@Roles(UserRole.ADMIN)
async getProviders() {
const providers = await this.providersService.findAll();
return { providers };
}
@Patch('providers/:id')
@Roles(UserRole.SUPER_ADMIN)
async updateProvider(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: UpdateProviderDto,
) {
const provider = await this.providersService.update(id, dto, req.user.id);
return {
message: 'Proveedor actualizado exitosamente',
provider,
};
}
// Credit Packages Endpoints
@Get('packages')
@Roles(UserRole.ADMIN)
async getPackages(@Query('includeInactive') includeInactive?: string) {
const packages = await this.packagesService.findAll(includeInactive === 'true');
return { packages };
}
@Post('packages')
@Roles(UserRole.ADMIN)
async createPackage(@Req() req: AuthRequest, @Body() dto: CreatePackageDto) {
const pkg = await this.packagesService.create(dto, req.user.id);
return {
message: 'Paquete creado exitosamente',
package: pkg,
};
}
@Patch('packages/:id')
@Roles(UserRole.ADMIN)
async updatePackage(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: UpdatePackageDto,
) {
const pkg = await this.packagesService.update(id, dto, req.user.id);
return {
message: 'Paquete actualizado exitosamente',
package: pkg,
};
}
// Promotions Endpoints
@Get('promotions')
@Roles(UserRole.ADMIN)
async getPromotions(@Query('includeExpired') includeExpired?: string) {
const promotions = await this.promotionsService.findAll(includeExpired === 'true');
return { promotions };
}
@Post('promotions')
@Roles(UserRole.ADMIN)
async createPromotion(@Req() req: AuthRequest, @Body() dto: CreatePromotionDto) {
const promotion = await this.promotionsService.create(dto, req.user.id);
return {
message: 'Promocion creada exitosamente',
promotion,
};
}
@Patch('promotions/:id')
@Roles(UserRole.ADMIN)
async updatePromotion(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: UpdatePromotionDto,
) {
const promotion = await this.promotionsService.update(id, dto, req.user.id);
return {
message: 'Promocion actualizada exitosamente',
promotion,
};
}
@Post('promotions/validate')
@Roles(UserRole.VIEWER)
async validatePromoCode(@Body() dto: ValidatePromoCodeDto) {
return this.promotionsService.validateCode(dto.code, dto.packageId, dto.purchaseAmount);
}
// Product Moderation Endpoints
@Get('products/pending')
@Roles(UserRole.MODERATOR)
async getPendingProducts(
@Query('page') page?: string,
@Query('limit') limit?: string,
) {
return this.moderationService.getPendingProducts(
page ? parseInt(page, 10) : 1,
limit ? parseInt(limit, 10) : 20,
);
}
@Post('products/:id/approve')
@Roles(UserRole.MODERATOR)
async approveProduct(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: ApproveProductDto,
) {
const product = await this.moderationService.approveProduct(id, dto, req.user.id);
return {
message: 'Producto aprobado exitosamente',
product,
};
}
@Post('products/:id/reject')
@Roles(UserRole.MODERATOR)
async rejectProduct(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: RejectProductDto,
) {
const product = await this.moderationService.rejectProduct(id, dto, req.user.id);
return {
message: 'Producto rechazado',
product,
};
}
// Referral Fraud Moderation Endpoints
@Get('referrals/fraud-holds')
@Roles(UserRole.MODERATOR)
async getFraudHoldReferrals(
@Query('page') page?: string,
@Query('limit') limit?: string,
) {
return this.moderationService.getFraudHoldReferrals(
page ? parseInt(page, 10) : 1,
limit ? parseInt(limit, 10) : 20,
);
}
@Post('referrals/:id/approve')
@Roles(UserRole.MODERATOR)
async approveReferral(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: ApproveReferralDto,
) {
const referral = await this.moderationService.approveReferral(id, dto, req.user.id);
return {
message: 'Referido aprobado exitosamente',
referral,
};
}
@Post('referrals/:id/reject')
@Roles(UserRole.MODERATOR)
async rejectReferral(
@Req() req: AuthRequest,
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: RejectReferralDto,
) {
const referral = await this.moderationService.rejectReferral(id, dto, req.user.id);
return {
message: 'Referido rechazado por fraude',
referral,
};
}
}