import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseGuards, } from '@nestjs/common'; import { IsBoolean, IsObject, IsOptional, IsString, MaxLength, } from 'class-validator'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { RequirePermission, SectionPermissionGuard } from '../auth/section-permission.guard'; import { CurrentUser } from '../auth/current-user.decorator'; import type { Actor } from '../common/record-scope'; import { SavedViewsService } from '../saved-views/saved-views.service'; import { ReportsBuilderQueryDto, ReportsDrilldownQueryDto, ReportsQueryDto } from './dto'; import { ReportsService } from './reports.service'; class CreateReportViewDto { @IsString() @MaxLength(120) name!: string; @IsObject() filters!: Record; @IsOptional() @IsBoolean() isShared?: boolean; } class UpdateReportViewDto { @IsOptional() @IsString() @MaxLength(120) name?: string; @IsOptional() @IsObject() filters?: Record; @IsOptional() @IsBoolean() isShared?: boolean; } @Controller('reports') @UseGuards(JwtAuthGuard, SectionPermissionGuard) @RequirePermission('reports', { reads: true }) export class ReportsController { constructor( private readonly reportsService: ReportsService, private readonly savedViews: SavedViewsService, ) {} @Get('dashboard') dashboard(@CurrentUser() user: Actor, @Query() query: ReportsQueryDto) { return this.reportsService.dashboard(user, { from: query.from, to: query.to, }); } @Get('drilldown') drilldown( @CurrentUser() user: Actor, @Query() query: ReportsDrilldownQueryDto, ) { return this.reportsService.drilldown(user, { kind: query.kind, id: query.id, from: query.from, to: query.to, }); } @Post('builder') builder( @CurrentUser() user: Actor, @Body() dto: ReportsBuilderQueryDto, ) { return this.reportsService.builder(user, { metric: dto.metric, dimension: dto.dimension, from: dto.from, to: dto.to, userId: dto.userId, teamId: dto.teamId, }); } /** داشبورد صفحهٔ خانه برای همه باز است */ @Get('home') @RequirePermission('reports', { reads: false }) home(@CurrentUser() user: Actor) { return this.reportsService.home(user); } @Get('views') listViews(@CurrentUser() user: Actor) { return this.savedViews.list(user.organizationId, user.userId, 'reports'); } @Get('views/:id') getView(@CurrentUser() user: Actor, @Param('id') id: string) { return this.savedViews.get(user.organizationId, user.userId, id, 'reports'); } @Post('views') createView(@CurrentUser() user: Actor, @Body() dto: CreateReportViewDto) { return this.savedViews.create(user.organizationId, user.userId, { name: dto.name, scope: 'reports', filters: dto.filters, isShared: dto.isShared, }); } @Patch('views/:id') updateView( @CurrentUser() user: Actor, @Param('id') id: string, @Body() dto: UpdateReportViewDto, ) { const isAdmin = user.role === 'owner' || user.role === 'admin'; return this.savedViews.update( user.organizationId, user.userId, id, { name: dto.name, filters: dto.filters, isShared: dto.isShared, scope: 'reports', }, isAdmin, 'reports', ); } @Delete('views/:id') async removeView(@CurrentUser() user: Actor, @Param('id') id: string) { const isAdmin = user.role === 'owner' || user.role === 'admin'; await this.savedViews.remove( user.organizationId, user.userId, id, isAdmin, 'reports', ); return { ok: true }; } }