initial commit

This commit is contained in:
2026-06-09 14:07:37 +03:30
parent 30ac533800
commit 996a4fcda7
121 changed files with 20557 additions and 3 deletions

View File

@@ -0,0 +1,140 @@
import {
Body,
Controller,
Post,
Req,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { Throttle } from '@nestjs/throttler';
import { Request } from 'express';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { InquiryAccessGuard } from '../auth/guards/inquiry-access.guard';
import { InquiryAccess } from '../auth/decorators/inquiry-access.decorator';
import { InquiryType } from '../common/enums/inquiry-type.enum';
import { BaseInquiryResponseDto } from '../common/dto/base-inquiry-response.dto';
import { ResponseTransformInterceptor } from '../common/interceptors/response-transform.interceptor';
import { UserRateLimitGuard } from '../rate-limit/user-rate-limit.guard';
import { PersonInquiryRequestDto } from './dto/person-inquiry-request.dto';
import { PersonInquiryDataDto } from './dto/person-inquiry-data.dto';
import { PersonInquiryResponseDto } from './dto/person-inquiry-response.dto';
import { GenericInquiryResponseDto } from './dto/generic-inquiry-response.dto';
import { PostalCodeRequestDto } from './dto/postal-code-request.dto';
import { ShahkarRequestDto } from './dto/shahkar-request.dto';
import { SayahRequestDto } from './dto/sayah-request.dto';
import { InquiryService } from './inquiry.service';
/**
* Unified inquiry endpoints — protected by JWT, inquiry RBAC, and rate limits.
*/
@ApiTags('Inquiries')
@ApiBearerAuth()
@Controller('inquiry')
@UseGuards(JwtAuthGuard, InquiryAccessGuard, UserRateLimitGuard)
@UseInterceptors(ResponseTransformInterceptor)
export class InquiryController {
constructor(private readonly inquiryService: InquiryService) {}
@Post('person')
@InquiryAccess(InquiryType.PERSON)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Person identity inquiry' })
@ApiResponse({ status: 200, type: PersonInquiryResponseDto })
@ApiResponse({ status: 401, description: 'Unauthorized' })
@ApiResponse({ status: 403, description: 'Inquiry access denied' })
@ApiResponse({ status: 429, description: 'Too many requests' })
async inquirePerson(
@Body() dto: PersonInquiryRequestDto,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<PersonInquiryDataDto>> {
const requestId = req.requestId ?? 'unknown';
const result = await this.inquiryService.inquirePerson(dto, requestId);
req.trackingCode = result.trackingCode;
return result;
}
@Post('realEstate')
@InquiryAccess(InquiryType.REAL_ESTATE)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Real estate inquiry' })
@ApiResponse({ status: 200, type: GenericInquiryResponseDto })
async inquireRealEstate(
@Body() payload: Record<string, unknown>,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
return this.inquireGeneric(InquiryType.REAL_ESTATE, payload, req);
}
@Post('sheba')
@InquiryAccess(InquiryType.SHEBA)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Sheba inquiry' })
@ApiResponse({ status: 200, type: GenericInquiryResponseDto })
async inquireSheba(
@Body() payload: SayahRequestDto,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
return this.inquireGeneric(InquiryType.SHEBA, payload as unknown as Record<string, unknown>, req);
}
@Post('shahkar')
@InquiryAccess(InquiryType.SHAHKAR)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Shahkar inquiry' })
@ApiResponse({ status: 200, type: GenericInquiryResponseDto })
async inquireShahkar(
@Body() payload: ShahkarRequestDto,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
return this.inquireGeneric(
InquiryType.SHAHKAR,
payload as unknown as Record<string, unknown>,
req,
);
}
@Post('postalCode')
@InquiryAccess(InquiryType.POSTAL_CODE)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Postal code inquiry' })
@ApiResponse({ status: 200, type: GenericInquiryResponseDto })
async inquirePostalCode(
@Body() payload: PostalCodeRequestDto,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
return this.inquireGeneric(
InquiryType.POSTAL_CODE,
payload as unknown as Record<string, unknown>,
req,
);
}
@Post('legalPerson')
@InquiryAccess(InquiryType.LEGAL_PERSON)
@Throttle({ default: { limit: 30, ttl: 60000 } })
@ApiOperation({ summary: 'Legal person inquiry' })
@ApiResponse({ status: 200, type: GenericInquiryResponseDto })
async inquireLegalPerson(
@Body() payload: Record<string, unknown>,
@Req() req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
return this.inquireGeneric(InquiryType.LEGAL_PERSON, payload, req);
}
private async inquireGeneric(
inquiryType: InquiryType,
payload: Record<string, unknown>,
req: Request & { requestId?: string; trackingCode?: string },
): Promise<BaseInquiryResponseDto<Record<string, unknown>>> {
const requestId = req.requestId ?? 'unknown';
const result = await this.inquiryService.inquire(inquiryType, payload, requestId);
req.trackingCode = result.trackingCode;
return result;
}
}