import { Get, Post, Put, Delete, Param, Query, Body, HttpCode, ParseUUIDPipe, } from '@nestjs/common'; import { ApiOperation, ApiOkResponse, ApiNotFoundResponse, ApiBadRequestResponse, } from '@nestjs/swagger'; import { BaseService } from './base.service'; import { PaginationDto } from '../dto/pagination.dto'; import { ApiResponse, createSuccessResponse, createPaginatedResponse, } from '../types/api-response.type'; /** * Generic base controller with common CRUD endpoints * Extend this class for entity-specific controllers * * Note: Use decorators like @Controller() on the child class */ export abstract class BaseController { constructor( protected readonly service: BaseService, protected readonly entityName: string, ) {} @Get() @HttpCode(200) @ApiOperation({ summary: 'Get all records with pagination' }) @ApiOkResponse({ description: 'Records retrieved successfully' }) async findAll( @Query() pagination: PaginationDto, ): Promise> { const result = await this.service.findAll(pagination); return createPaginatedResponse( result.items, result.meta.total, result.meta.page, result.meta.limit, `${this.entityName} list retrieved successfully`, ); } @Get(':id') @HttpCode(200) @ApiOperation({ summary: 'Get a record by ID' }) @ApiOkResponse({ description: 'Record retrieved successfully' }) @ApiNotFoundResponse({ description: 'Record not found' }) async findOne( @Param('id', ParseUUIDPipe) id: string, ): Promise> { const result = await this.service.findOne(id); return createSuccessResponse( result, `${this.entityName} retrieved successfully`, ); } @Post() @HttpCode(200) @ApiOperation({ summary: 'Create a new record' }) @ApiOkResponse({ description: 'Record created successfully' }) @ApiBadRequestResponse({ description: 'Validation failed' }) async create(@Body() createDto: CreateDto): Promise> { const result = await this.service.create(createDto); return createSuccessResponse( result, `${this.entityName} created successfully`, 201, ); } @Put(':id') @HttpCode(200) @ApiOperation({ summary: 'Update an existing record' }) @ApiOkResponse({ description: 'Record updated successfully' }) @ApiNotFoundResponse({ description: 'Record not found' }) async update( @Param('id', ParseUUIDPipe) id: string, @Body() updateDto: UpdateDto, ): Promise> { const result = await this.service.update(id, updateDto); return createSuccessResponse( result, `${this.entityName} updated successfully`, ); } @Delete(':id') @HttpCode(200) @ApiOperation({ summary: 'Delete a record (soft delete)' }) @ApiOkResponse({ description: 'Record deleted successfully' }) @ApiNotFoundResponse({ description: 'Record not found' }) async delete( @Param('id', ParseUUIDPipe) id: string, ): Promise> { const result = await this.service.delete(id); return createSuccessResponse( result, `${this.entityName} deleted successfully`, ); } @Post(':id/restore') @HttpCode(200) @ApiOperation({ summary: 'Restore a soft-deleted record' }) @ApiOkResponse({ description: 'Record restored successfully' }) async restore( @Param('id', ParseUUIDPipe) id: string, ): Promise> { const result = await this.service.restore(id); return createSuccessResponse( result, `${this.entityName} restored successfully`, ); } }