feat(10-05): add SourceConfigDto and TenderQueryDto
- SourceConfigDto: pollIntervalMin (@Min(5) @Max(1440)), isActive - TenderQueryDto: page/limit pagination (copied from DkvHistoryQueryDto) + status filter
This commit is contained in:
@@ -0,0 +1,35 @@
|
|||||||
|
import { IsBoolean, IsInt, IsOptional, Max, Min } from 'class-validator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DTO for reading/updating the singleton `doe-opendata` poll config
|
||||||
|
* (`TenderSourcePollConfig`, `sourceType: 'doe-opendata'`).
|
||||||
|
*
|
||||||
|
* Security:
|
||||||
|
* - T-10-15: pollIntervalMin bounded 5-1440 — same DoS-mitigation floor as
|
||||||
|
* DkvConfigDto.pollIntervalMin (no sub-5-minute polling of the platform-wide
|
||||||
|
* scheduler).
|
||||||
|
*
|
||||||
|
* Note: `pollIntervalMin` is the cron-tick frequency (D-04 default 60) —
|
||||||
|
* NOT the DÖE fetch frequency. The actual upstream HTTP call is gated
|
||||||
|
* separately by the day-cursor check inside TenderIngestionService
|
||||||
|
* (Pitfall A: cron tick frequency != actual-fetch frequency for this
|
||||||
|
* day-granular source).
|
||||||
|
*/
|
||||||
|
export class SourceConfigDto {
|
||||||
|
/**
|
||||||
|
* Cron-tick interval in minutes. Minimum 5 minutes (DoS mitigation, T-10-15).
|
||||||
|
* Maximum 1440 (24h).
|
||||||
|
*/
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@Min(5)
|
||||||
|
@Max(1440)
|
||||||
|
pollIntervalMin?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the platform-wide DÖE poll cron job is active.
|
||||||
|
*/
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { Type } from 'class-transformer';
|
||||||
|
import { IsIn, IsInt, IsOptional, Max, Min } from 'class-validator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query DTO for paginating + filtering the global tender catalog.
|
||||||
|
*
|
||||||
|
* Security:
|
||||||
|
* - T-10-15: pagination bounds (limit @Max(100)) mitigate oversized
|
||||||
|
* result-set DoS — same convention as DkvHistoryQueryDto.
|
||||||
|
*
|
||||||
|
* Used for: GET /modules/tender-radar?page=1&limit=20&status=active
|
||||||
|
*
|
||||||
|
* No region/CPV filters here — rich filtering is Phase 11 (FILTER-*).
|
||||||
|
*/
|
||||||
|
export class TenderQueryDto {
|
||||||
|
/**
|
||||||
|
* Page number (1-based). Defaults to 1 when omitted.
|
||||||
|
* @Type(() => Number) coerces the query-string value to a number before
|
||||||
|
* validation — required because HTTP query params always arrive as strings.
|
||||||
|
*/
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@Min(1)
|
||||||
|
@Type(() => Number)
|
||||||
|
page?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of records per page. Defaults to 20 when omitted.
|
||||||
|
* T-10-15: bounded integer mitigates oversized result-set DoS.
|
||||||
|
*/
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@Min(1)
|
||||||
|
@Max(100)
|
||||||
|
@Type(() => Number)
|
||||||
|
limit?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status filter. Defaults to active-only at the query layer when omitted.
|
||||||
|
*/
|
||||||
|
@IsOptional()
|
||||||
|
@IsIn(['active', 'expired'])
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user