diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 36af21989..000000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx lint-staged diff --git a/src/modules/billing-plans/billing-plan.controller.ts b/src/modules/billing-plans/billing-plan.controller.ts index 180313f3a..525fb5097 100644 --- a/src/modules/billing-plans/billing-plan.controller.ts +++ b/src/modules/billing-plans/billing-plan.controller.ts @@ -10,6 +10,7 @@ import { Delete, HttpCode, HttpStatus, + Query } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; import { SuperAdminGuard } from '../../guards/super-admin.guard'; @@ -40,8 +41,13 @@ export class BillingPlanController { @skipAuth() @getAllBillingPlansDocs() @Get('/') - async getAllBillingPlans() { - return this.billingPlanService.getAllBillingPlans(); + async getAllBillingPlans( + @Query('page') page: string, + @Query('limit') limit: string, ) + { + const pageNumber = page ? parseInt(page, 10) : 1; + const limitNumber = limit ? parseInt(limit, 10) : 10; + return this.billingPlanService.getAllBillingPlans(pageNumber, limitNumber); } @skipAuth() diff --git a/src/modules/billing-plans/billing-plan.service.ts b/src/modules/billing-plans/billing-plan.service.ts index f9bd94c63..3340ca96b 100644 --- a/src/modules/billing-plans/billing-plan.service.ts +++ b/src/modules/billing-plans/billing-plan.service.ts @@ -45,8 +45,15 @@ export class BillingPlanService { }; } - async getAllBillingPlans() { - const allPlans = await this.billingPlanRepository.find(); + async getAllBillingPlans(page: number = 1, limit: number = 10) { + const skip = (page - 1) * limit; + const take = limit; + + const [allPlans, total] = await this.billingPlanRepository.findAndCount({ + skip, + take, + }); + if (allPlans.length === 0) { throw new NotFoundException('No billing plans found'); } @@ -54,7 +61,10 @@ export class BillingPlanService { return { message: 'Billing plans retrieved successfully', - data: plans, + data: { + plans, + total, + }, }; } diff --git a/src/modules/billing-plans/docs/billing-plan-docs.ts b/src/modules/billing-plans/docs/billing-plan-docs.ts index 97faf5c4e..27c91f4ba 100644 --- a/src/modules/billing-plans/docs/billing-plan-docs.ts +++ b/src/modules/billing-plans/docs/billing-plan-docs.ts @@ -1,6 +1,6 @@ import { applyDecorators } from '@nestjs/common'; import { BillingPlanDto } from '../dto/billing-plan.dto'; -import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiQuery} from '@nestjs/swagger'; import { BillingPlan } from '../entities/billing-plan.entity'; export function createBillingPlanDocs() { @@ -15,8 +15,29 @@ export function createBillingPlanDocs() { export function getAllBillingPlansDocs() { return applyDecorators( - ApiOperation({ summary: 'Get all billing plans' }), - ApiResponse({ status: 200, description: 'Billing plans retrieved successfully.', type: [BillingPlanDto] }), + ApiOperation({ summary: 'Get all billing plans (paginated)' }), + ApiQuery({ name: 'page', required: false, description: 'Page number (default: 1)' }), + ApiQuery({ name: 'limit', required: false, description: 'Number of items per page (default: 10)' }), + ApiResponse({ + status: 200, + description: 'Billing plans retrieved successfully.', + schema: { + type: 'object', + properties: { + message: { type: 'string', example: 'Billing plans retrieved successfully' }, + data: { + type: 'object', + properties: { + plans: { + type: 'array', + items: { type: 'object', $ref: '#/components/schemas/BillingPlanDto' }, // Use a $ref to your BillingPlanDto schema + }, + total: { type: 'number', example: 123 }, + }, + }, + }, + }, + }), ApiResponse({ status: 404, description: 'No billing plans found.' }) ); } diff --git a/src/modules/billing-plans/tests/billing-plan.service.spec.ts b/src/modules/billing-plans/tests/billing-plan.service.spec.ts index 7c72994a9..26fa2fc2d 100644 --- a/src/modules/billing-plans/tests/billing-plan.service.spec.ts +++ b/src/modules/billing-plans/tests/billing-plan.service.spec.ts @@ -67,7 +67,7 @@ describe('BillingPlanService', () => { }); describe('getAllBillingPlans', () => { - it('should return all billing plans', async () => { + it('should return paginated billing plans', async () => { const billingPlans = [ { id: '1', @@ -105,25 +105,40 @@ describe('BillingPlanService', () => { expirationDate: new Date(), email: 'test3@example.com', }, - ]; - - jest.spyOn(repository, 'find').mockResolvedValue(billingPlans as BillingPlan[]); - - const result = await service.getAllBillingPlans(); + ]; + + const total = 2; // Total number of billing plans in the database + + // Mock findAndCount to return paginated results + jest.spyOn(repository, 'findAndCount').mockResolvedValue([billingPlans as BillingPlan[], total]); + + const result = await service.getAllBillingPlans(1, 10); + + // Verify the response structure expect(result).toEqual({ message: 'Billing plans retrieved successfully', - data: billingPlans.map(plan => BillingPlanMapper.mapToResponseFormat(plan)), + data: { + plans: billingPlans.map(plan => BillingPlanMapper.mapToResponseFormat(plan)), + total, + }, + }); + + // Verify that findAndCount was called with the correct pagination parameters + expect(repository.findAndCount).toHaveBeenCalledWith({ + skip: 0, // (page - 1) * limit = (1 - 1) * 10 = 0 + take: 10, // limit = 10 }); }); - + it('should throw a NotFoundException if no billing plans are found', async () => { - jest.spyOn(repository, 'find').mockResolvedValue([]); - - await expect(service.getAllBillingPlans()).rejects.toThrow(NotFoundException); + // Mock findAndCount to return an empty array + jest.spyOn(repository, 'findAndCount').mockResolvedValue([[], 0]); + + await expect(service.getAllBillingPlans(1, 10)).rejects.toThrow(NotFoundException); }); }); - + describe('getSingleBillingPlan', () => { it('should return a single billing plan', async () => { const billingPlan = {