test(auth): add unit tests for KYC presigned upload and submit handlers
Cover GenerateKycUploadUrlsHandler (10 tests) and SubmitKycHandler (10 tests): presigned URL flow, legacy file upload, status validation, error handling. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Query,
|
||||
@@ -12,7 +13,7 @@ import {
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { type CommandBus, type QueryBus } from '@nestjs/cqrs';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery } from '@nestjs/swagger';
|
||||
import { JwtAuthGuard } from '@modules/auth';
|
||||
import { RequireQuota, QuotaGuard } from '@modules/subscriptions';
|
||||
import { DeleteReportCommand } from '../../application/commands/delete-report/delete-report.command';
|
||||
@@ -22,6 +23,7 @@ import { GetReportQuery } from '../../application/queries/get-report/get-report.
|
||||
import { type ListReportsResult } from '../../application/queries/list-reports/list-reports.handler';
|
||||
import { ListReportsQuery } from '../../application/queries/list-reports/list-reports.query';
|
||||
import { type ReportEntity } from '../../domain/entities/report.entity';
|
||||
import { MACRO_DATA_SERVICE, type IMacroDataService } from '../../domain/services/macro-data.service';
|
||||
import { type GenerateReportDto } from '../dto/generate-report.dto';
|
||||
import { type ListReportsDto } from '../dto/list-reports.dto';
|
||||
|
||||
@@ -35,6 +37,7 @@ export class ReportsController {
|
||||
constructor(
|
||||
private readonly commandBus: CommandBus,
|
||||
private readonly queryBus: QueryBus,
|
||||
@Inject(MACRO_DATA_SERVICE) private readonly macroDataService: IMacroDataService,
|
||||
) {}
|
||||
|
||||
@Post('generate')
|
||||
@@ -70,6 +73,60 @@ export class ReportsController {
|
||||
};
|
||||
}
|
||||
|
||||
@Get('macro-data')
|
||||
@ApiOperation({ summary: 'Dữ liệu kinh tế vĩ mô theo tỉnh' })
|
||||
@ApiQuery({ name: 'province', required: true, description: 'Province name' })
|
||||
@ApiQuery({ name: 'categories', required: false, isArray: true, description: 'Indicator categories to retrieve' })
|
||||
@ApiQuery({ name: 'fromYear', required: false, description: 'Start year (default 2020)' })
|
||||
@ApiQuery({ name: 'toYear', required: false, description: 'End year (default 2025)' })
|
||||
@ApiResponse({ status: 200, description: 'Macro-economic data grouped by indicator' })
|
||||
async getMacroData(
|
||||
@Query('province') province: string,
|
||||
@Query('categories') categories?: string | string[],
|
||||
@Query('fromYear') fromYear?: string,
|
||||
@Query('toYear') toYear?: string,
|
||||
) {
|
||||
const indicators = categories
|
||||
? Array.isArray(categories) ? categories : [categories]
|
||||
: undefined;
|
||||
const from = fromYear ? parseInt(fromYear, 10) : 2020;
|
||||
const to = toYear ? parseInt(toYear, 10) : 2025;
|
||||
|
||||
const rows = await this.macroDataService.getByProvince(province, indicators);
|
||||
|
||||
// Filter by year range and group by indicator
|
||||
type MacroPoint = { year: number; value: number; unit: string; yoy_change: number | null };
|
||||
const grouped = new Map<string, MacroPoint[]>();
|
||||
for (const row of rows) {
|
||||
const year = parseInt(row.period, 10);
|
||||
if (isNaN(year) || year < from || year > to) continue;
|
||||
let series = grouped.get(row.indicator);
|
||||
if (!series) {
|
||||
series = [];
|
||||
grouped.set(row.indicator, series);
|
||||
}
|
||||
series.push({ year, value: row.value, unit: row.unit, yoy_change: null });
|
||||
}
|
||||
|
||||
// Sort each group by year and compute YoY change
|
||||
for (const series of grouped.values()) {
|
||||
series.sort((a, b) => a.year - b.year);
|
||||
for (let i = 1; i < series.length; i++) {
|
||||
const prev = series[i - 1]!;
|
||||
const curr = series[i]!;
|
||||
if (prev.value !== 0) {
|
||||
curr.yoy_change = parseFloat((((curr.value - prev.value) / prev.value) * 100).toFixed(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
province,
|
||||
data: Object.fromEntries(grouped),
|
||||
highlights: [],
|
||||
};
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiBearerAuth('JWT')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
||||
Reference in New Issue
Block a user