From 83f1e5cea709f4354154b8782e11e4e12dd8a51c Mon Sep 17 00:00:00 2001 From: gchauhan-aot <113390759+gchauhan-aot@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:36:34 -0700 Subject: [PATCH] ORV2-1700 Changes for Pagination, API Specification And Permit Endpoint (#929) Co-authored-by: Krishnan Subramanian --- frontend/src/common/types/common.ts | 33 +++- .../features/idir/search/api/idirSearch.ts | 9 +- .../search/components/IDIRSearchResults.tsx | 4 +- .../permits/apiManager/endpoints/endpoints.ts | 1 - .../features/permits/apiManager/permitsAPI.ts | 6 +- .../components/permit-list/BasePermitList.tsx | 4 +- vehicles/src/common/class/pagination.ts | 14 -- .../common/decorator/api-paginate-response.ts | 27 +++ vehicles/src/common/dto/paginate/page-meta.ts | 31 ++++ .../src/common/dto/paginate/page-options.ts | 31 ++++ .../src/common/dto/paginate/pagination.ts | 17 ++ vehicles/src/common/helper/paginate.ts | 167 ------------------ .../src/common/helper/pagination.helper.ts | 38 ---- .../common/interface/pagination.interface.ts | 76 +------- .../src/modules/permit/permit.controller.ts | 66 ++----- vehicles/src/modules/permit/permit.service.ts | 62 +++---- 16 files changed, 193 insertions(+), 393 deletions(-) delete mode 100644 vehicles/src/common/class/pagination.ts create mode 100644 vehicles/src/common/decorator/api-paginate-response.ts create mode 100644 vehicles/src/common/dto/paginate/page-meta.ts create mode 100644 vehicles/src/common/dto/paginate/page-options.ts create mode 100644 vehicles/src/common/dto/paginate/pagination.ts delete mode 100644 vehicles/src/common/helper/paginate.ts delete mode 100644 vehicles/src/common/helper/pagination.helper.ts diff --git a/frontend/src/common/types/common.ts b/frontend/src/common/types/common.ts index b840fffa5..db0001c55 100644 --- a/frontend/src/common/types/common.ts +++ b/frontend/src/common/types/common.ts @@ -34,9 +34,15 @@ export type ORBC_FormTypes = * The options for pagination. */ export type PaginationOptions = { + /** + * The page number to fetch. + */ page: number; - limit: number; -} + /** + * The number of items in the current page. + */ + take: number; +}; /** * A generic paginated response structure for all the paginated responses from APIs. @@ -56,12 +62,23 @@ export type PaginatedResponse = { * The metadata containing info about a page in the paginated response. */ export type PageMetadataInResponse = { - currentPage: number; - currentItemCount: number; - itemsPerPage: number; - totalPages?: number; - totalItems?: number; -}; + /** + * The total items matching the query in the database. + */ + totalItems: number; + /** + * The total number of pages. + */ + pageCount: number; + /** + * Is there a previous page? + */ + hasPreviousPage: boolean; + /** + * Is there a next page? + */ + hasNextPage: boolean; +} & PaginationOptions; export type Optional = T | undefined; export type RequiredOrNull = T | null; diff --git a/frontend/src/features/idir/search/api/idirSearch.ts b/frontend/src/features/idir/search/api/idirSearch.ts index 3fe34050c..aba386346 100644 --- a/frontend/src/features/idir/search/api/idirSearch.ts +++ b/frontend/src/features/idir/search/api/idirSearch.ts @@ -1,6 +1,9 @@ import { VEHICLES_URL } from "../../../../common/apiManager/endpoints/endpoints"; import { httpGETRequest } from "../../../../common/apiManager/httpRequestHandler"; -import { PaginatedResponse, PaginationOptions } from "../../../../common/types/common"; +import { + PaginatedResponse, + PaginationOptions, +} from "../../../../common/types/common"; import { Permit } from "../../../permits/types/permit"; import { SearchFields } from "../types/types"; @@ -11,12 +14,12 @@ import { SearchFields } from "../types/types"; */ export const getDataBySearch = ( { searchEntity, searchByFilter, searchValue }: SearchFields, - { page = 0, limit = 10 }: PaginationOptions, + { page = 0, take = 10 }: PaginationOptions, ): Promise> => { const searchURL = new URL(`${VEHICLES_URL}/${searchEntity}/ppc/search`); searchURL.searchParams.set("searchColumn", searchByFilter); searchURL.searchParams.set("searchString", searchValue); searchURL.searchParams.set("page", (page + 1).toString()); - searchURL.searchParams.set("limit", (limit).toString()); + searchURL.searchParams.set("take", take.toString()); return httpGETRequest(searchURL.toString()).then((response) => response.data); }; diff --git a/frontend/src/features/idir/search/components/IDIRSearchResults.tsx b/frontend/src/features/idir/search/components/IDIRSearchResults.tsx index d5568497a..80c029f0c 100644 --- a/frontend/src/features/idir/search/components/IDIRSearchResults.tsx +++ b/frontend/src/features/idir/search/components/IDIRSearchResults.tsx @@ -86,7 +86,7 @@ export const IDIRSearchResults = memo( searchEntity, searchValue, }, - { page: pagination.pageIndex, limit: pagination.pageSize }, + { page: pagination.pageIndex, take: pagination.pageSize }, ), { retry: 1, // retry once. @@ -140,7 +140,7 @@ export const IDIRSearchResults = memo( autoResetPageIndex: false, manualPagination: true, rowCount: data?.meta?.totalItems ?? 0, - pageCount: data?.meta?.totalPages ?? 0, + pageCount: data?.meta?.pageCount ?? 0, onPaginationChange: setPagination, enablePagination: true, enableTopToolbar: true, diff --git a/frontend/src/features/permits/apiManager/endpoints/endpoints.ts b/frontend/src/features/permits/apiManager/endpoints/endpoints.ts index 365c49843..3996a61be 100644 --- a/frontend/src/features/permits/apiManager/endpoints/endpoints.ts +++ b/frontend/src/features/permits/apiManager/endpoints/endpoints.ts @@ -15,7 +15,6 @@ export const APPLICATIONS_API_ROUTES = { export const PERMITS_API_ROUTES = { BASE: PERMITS_API_BASE, GET: PERMITS_API_BASE, - GET_LIST: `${PERMITS_API_BASE}/user`, ISSUE: `${APPLICATIONS_API_BASE}/issue`, HISTORY: `${PERMITS_API_BASE}/history`, AMEND: APPLICATIONS_API_ROUTES.CREATE, diff --git a/frontend/src/features/permits/apiManager/permitsAPI.ts b/frontend/src/features/permits/apiManager/permitsAPI.ts index bb86313bb..379bc936b 100644 --- a/frontend/src/features/permits/apiManager/permitsAPI.ts +++ b/frontend/src/features/permits/apiManager/permitsAPI.ts @@ -386,10 +386,10 @@ export const getCurrentAmendmentApplication = async ( */ export const getPermits = async ( { expired = false } = {}, - { page = 0, limit = 10 }: PaginationOptions, + { page = 0, take = 10 }: PaginationOptions, ): Promise> => { const companyId = getDefaultRequiredVal("", getCompanyIdFromSession()); - const permitsURL = new URL(PERMITS_API_ROUTES.GET_LIST); + const permitsURL = new URL(PERMITS_API_ROUTES.GET); if (companyId) { permitsURL.searchParams.set("companyId", companyId); } @@ -397,7 +397,7 @@ export const getPermits = async ( permitsURL.searchParams.set("expired", "true"); } permitsURL.searchParams.set("page", (page + 1).toString()); - permitsURL.searchParams.set("limit", limit.toString()); + permitsURL.searchParams.set("take", take.toString()); const permits = await httpGETRequest(permitsURL.toString()) .then((response) => { const paginatedResponseObject = getDefaultRequiredVal( diff --git a/frontend/src/features/permits/components/permit-list/BasePermitList.tsx b/frontend/src/features/permits/components/permit-list/BasePermitList.tsx index 901bf5f63..3fe50edf1 100644 --- a/frontend/src/features/permits/components/permit-list/BasePermitList.tsx +++ b/frontend/src/features/permits/components/permit-list/BasePermitList.tsx @@ -44,7 +44,7 @@ export const BasePermitList = ({ queryFn: () => getPermits( { expired: isExpired }, - { page: pagination.pageIndex, limit: pagination.pageSize }, + { page: pagination.pageIndex, take: pagination.pageSize }, ), keepPreviousData: true, staleTime: FIVE_MINUTES, @@ -87,7 +87,7 @@ export const BasePermitList = ({ autoResetPageIndex: false, manualPagination: true, rowCount: data?.meta?.totalItems ?? 0, - pageCount: data?.meta?.totalPages ?? 0, + pageCount: data?.meta?.pageCount ?? 0, onPaginationChange: setPagination, enablePagination: true, enableBottomToolbar: true, diff --git a/vehicles/src/common/class/pagination.ts b/vehicles/src/common/class/pagination.ts deleted file mode 100644 index 7c4235052..000000000 --- a/vehicles/src/common/class/pagination.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { IPaginationMeta } from '../interface/pagination.interface'; - -export class PaginationDto { - constructor( - /** - * a list of items to be returned - */ - public readonly items: PaginationObject[], - /** - * associated meta information (e.g., counts) - */ - public readonly meta: T, - ) {} -} diff --git a/vehicles/src/common/decorator/api-paginate-response.ts b/vehicles/src/common/decorator/api-paginate-response.ts new file mode 100644 index 000000000..95f4383ef --- /dev/null +++ b/vehicles/src/common/decorator/api-paginate-response.ts @@ -0,0 +1,27 @@ +import { applyDecorators, Type } from '@nestjs/common'; +import { ApiExtraModels, ApiOkResponse, getSchemaPath } from '@nestjs/swagger'; +import { PaginationDto } from '../dto/paginate/pagination'; + +export const ApiPaginatedResponse = >( + model: TModel, +) => { + return applyDecorators( + ApiExtraModels(PaginationDto), + ApiOkResponse({ + description: 'Successfully received model list', + schema: { + allOf: [ + { $ref: getSchemaPath(PaginationDto) }, + { + properties: { + items: { + type: 'array', + items: { $ref: getSchemaPath(model) }, + }, + }, + }, + ], + }, + }), + ); +}; diff --git a/vehicles/src/common/dto/paginate/page-meta.ts b/vehicles/src/common/dto/paginate/page-meta.ts new file mode 100644 index 000000000..284bd0adb --- /dev/null +++ b/vehicles/src/common/dto/paginate/page-meta.ts @@ -0,0 +1,31 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { PageMetaDtoParameters } from '../../interface/pagination.interface'; + +export class PageMetaDto { + @ApiProperty() + readonly page: number; + + @ApiProperty() + readonly take: number; + + @ApiProperty() + readonly totalItems: number; + + @ApiProperty() + readonly pageCount: number; + + @ApiProperty() + readonly hasPreviousPage: boolean; + + @ApiProperty() + readonly hasNextPage: boolean; + + constructor({ pageOptionsDto, totalItems }: PageMetaDtoParameters) { + this.page = pageOptionsDto.page; + this.take = pageOptionsDto.take; + this.totalItems = totalItems; + this.pageCount = Math.ceil(this.totalItems / this.take); + this.hasPreviousPage = this.page > 1; + this.hasNextPage = this.page < this.pageCount; + } +} diff --git a/vehicles/src/common/dto/paginate/page-options.ts b/vehicles/src/common/dto/paginate/page-options.ts new file mode 100644 index 000000000..96d34ef36 --- /dev/null +++ b/vehicles/src/common/dto/paginate/page-options.ts @@ -0,0 +1,31 @@ +import { ApiPropertyOptional } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; +import { IsInt, IsOptional, Max, Min } from 'class-validator'; + +export class PageOptionsDto { + @ApiPropertyOptional({ + minimum: 1, + default: 1, + }) + @Type(() => Number) + @IsInt() + @Min(1) + @IsOptional() + readonly page?: number = 1; + + @ApiPropertyOptional({ + minimum: 1, + maximum: 25, + default: 10, + }) + @Type(() => Number) + @IsInt() + @Min(1) + @Max(25) + @IsOptional() + readonly take?: number = 10; + + get skip(): number { + return (this.page - 1) * this.take; + } +} diff --git a/vehicles/src/common/dto/paginate/pagination.ts b/vehicles/src/common/dto/paginate/pagination.ts new file mode 100644 index 000000000..3baf53338 --- /dev/null +++ b/vehicles/src/common/dto/paginate/pagination.ts @@ -0,0 +1,17 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsArray } from 'class-validator'; +import { PageMetaDto } from './page-meta'; + +export class PaginationDto { + @IsArray() + @ApiProperty({ isArray: true }) + readonly items: T[]; + + @ApiProperty({ type: () => PageMetaDto }) + readonly meta: PageMetaDto; + + constructor(items: T[], meta: PageMetaDto) { + this.items = items; + this.meta = meta; + } +} diff --git a/vehicles/src/common/helper/paginate.ts b/vehicles/src/common/helper/paginate.ts deleted file mode 100644 index 473bffbfd..000000000 --- a/vehicles/src/common/helper/paginate.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { - Repository, - FindManyOptions, - SelectQueryBuilder, - FindOptionsWhere, -} from 'typeorm'; -import { PaginationDto } from '../class/pagination'; -import { - IPaginationMeta, - IPaginationOptions, - PaginationTypeEnum, - TypeORMCacheType, -} from '../interface/pagination.interface'; -import { createPaginationObject } from './pagination.helper'; -import { Logger } from '@nestjs/common'; - -const DEFAULT_LIMIT = 10; -const DEFAULT_PAGE = 1; - -const logger = new Logger('Paginate'); - -export async function paginate( - repositoryOrQueryBuilder: Repository | SelectQueryBuilder, - options: IPaginationOptions, - searchOptions?: FindOptionsWhere | FindManyOptions, -) { - return repositoryOrQueryBuilder instanceof Repository - ? paginateRepository( - repositoryOrQueryBuilder, - options, - searchOptions, - ) - : paginateQueryBuilder( - repositoryOrQueryBuilder, - options, - ); -} - -function resolveOptions( - options: IPaginationOptions, -): [number, number, PaginationTypeEnum, boolean, TypeORMCacheType] { - const page = resolveNumericOption(options, 'page', DEFAULT_PAGE); - const limit = resolveNumericOption(options, 'limit', DEFAULT_LIMIT); - const paginationType = - options.paginationType || PaginationTypeEnum.LIMIT_AND_OFFSET; - const countQueries = - typeof options.countQueries !== 'undefined' ? options.countQueries : true; - const cacheQueries = options.cacheQueries || false; - - return [page, limit, paginationType, countQueries, cacheQueries]; -} - -function resolveNumericOption( - options: IPaginationOptions, - key: 'page' | 'limit', - defaultValue: number, -): number { - const value = options[key]; - const resolvedValue = Number(value); - - if (Number.isInteger(resolvedValue) && resolvedValue >= 0) - return resolvedValue; - - logger.warn( - `Query parameter "${key}" with value "${value}" was resolved as "${resolvedValue}", please validate your query input! Falling back to default "${defaultValue}".`, - ); - return defaultValue; -} - -async function paginateRepository( - repository: Repository, - options: IPaginationOptions, - searchOptions?: FindOptionsWhere | FindManyOptions, -): Promise> { - const [page, limit, countQueries] = resolveOptions(options); - - if (page < 1) { - return createPaginationObject({ - items: [], - totalItems: 0, - currentPage: page, - limit, - metaTransformer: options.metaTransformer, - }); - } - - const promises: [Promise, Promise | undefined] = [ - repository.find({ - skip: limit * (page - 1), - take: limit, - ...searchOptions, - }), - undefined, - ]; - - if (countQueries) { - promises[1] = repository.count({ - ...searchOptions, - }); - } - - const [items, total] = await Promise.all(promises); - - return createPaginationObject({ - items, - totalItems: total, - currentPage: page, - limit, - metaTransformer: options.metaTransformer, - }); -} - -async function paginateQueryBuilder( - queryBuilder: SelectQueryBuilder, - options: IPaginationOptions, -): Promise> { - const [page, limit, paginationType, countQueries, cacheOption] = - resolveOptions(options); - - const promises: [Promise, Promise | undefined] = [ - (PaginationTypeEnum.LIMIT_AND_OFFSET === paginationType - ? queryBuilder.limit(limit).offset((page - 1) * limit) - : queryBuilder.take(limit).skip((page - 1) * limit) - ) - .cache(cacheOption) - .getMany(), - undefined, - ]; - - if (countQueries) { - promises[1] = countQuery(queryBuilder, cacheOption); - } - - const [items, total] = await Promise.all(promises); - - return createPaginationObject({ - items, - totalItems: total, - currentPage: page, - limit, - metaTransformer: options.metaTransformer, - }); -} - -const countQuery = async ( - queryBuilder: SelectQueryBuilder, - cacheOption: TypeORMCacheType, -): Promise => { - const totalQueryBuilder = queryBuilder.clone(); - - totalQueryBuilder - .skip(undefined) - .limit(undefined) - .offset(undefined) - .take(undefined) - .orderBy(undefined); - - const { value } = await queryBuilder.connection - .createQueryBuilder() - .select('COUNT(*)', 'value') - .from(`(${totalQueryBuilder.getQuery()})`, 'uniqueTableAlias') - .cache(cacheOption) - .setParameters(queryBuilder.getParameters()) - .getRawOne<{ value: string }>(); - - return Number(value); -}; diff --git a/vehicles/src/common/helper/pagination.helper.ts b/vehicles/src/common/helper/pagination.helper.ts deleted file mode 100644 index c6e67d5ed..000000000 --- a/vehicles/src/common/helper/pagination.helper.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { IPaginationMeta } from '../interface/pagination.interface'; -import { PaginationDto } from '../class/pagination'; - -export const createPaginationObject = ({ - items, - totalItems, - currentPage, - limit, - metaTransformer, -}: { - items: T[]; - totalItems?: number; - currentPage: number; - limit: number; - route?: string; - metaTransformer?: (metadata: IPaginationMeta) => CustomMetaType; -}) => { - const totalPages = - totalItems !== undefined ? Math.ceil(totalItems / limit) : undefined; - - const metadata: IPaginationMeta = { - totalItems, - currentItemCount: items.length, - itemsPerPage: limit, - totalPages, - currentPage: currentPage, - }; - - if (metaTransformer) - return new PaginationDto( - items, - metaTransformer(metadata), - ); - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return new PaginationDto(items, metadata); -}; diff --git a/vehicles/src/common/interface/pagination.interface.ts b/vehicles/src/common/interface/pagination.interface.ts index 2201108bb..3bdbb8baf 100644 --- a/vehicles/src/common/interface/pagination.interface.ts +++ b/vehicles/src/common/interface/pagination.interface.ts @@ -1,74 +1,6 @@ -export enum PaginationTypeEnum { - LIMIT_AND_OFFSET = 'limit', - TAKE_AND_SKIP = 'take', -} - -export interface IPaginationOptions { - /** - * @default 10 - * the amount of items to be requested per page - */ - limit: number | string; - - /** - * @default 1 - * the page that is requested - */ - page: number | string; - - /** - * For transforming the default meta data to a custom type - */ - metaTransformer?: (metadata: IPaginationMeta) => CustomMetaType; - - /** - * @default PaginationTypeEnum.LIMIT - * Used for changing query method to take/skip (defaults to limit/offset if no argument supplied) - */ - paginationType?: PaginationTypeEnum; - - /** - * @default true - * Turn off pagination count total queries. itemCount, totalItems, itemsPerPage and totalPages will be undefined - */ - countQueries?: boolean; - - /** - * @default false - * @link https://orkhan.gitbook.io/typeorm/docs/caching - * - * Enables or disables query result caching. - */ - cacheQueries?: TypeORMCacheType; -} - -export type TypeORMCacheType = - | boolean - | number - | { - id: unknown; - milliseconds: number; - }; +import { PageOptionsDto } from '../dto/paginate/page-options'; -export interface IPaginationMeta { - /** - * the amount of items on this specific page - */ - currentItemCount: number; - /** - * the total amount of items - */ - totalItems?: number; - /** - * the amount of items that were requested per page - */ - itemsPerPage: number; - /** - * the total amount of pages in this paginator - */ - totalPages?: number; - /** - * the current page this paginator "points" to - */ - currentPage: number; +export interface PageMetaDtoParameters { + pageOptionsDto: PageOptionsDto; + totalItems: number; } diff --git a/vehicles/src/modules/permit/permit.controller.ts b/vehicles/src/modules/permit/permit.controller.ts index ff02a3e8d..b7c1d4828 100644 --- a/vehicles/src/modules/permit/permit.controller.ts +++ b/vehicles/src/modules/permit/permit.controller.ts @@ -7,8 +7,6 @@ import { Param, Query, Res, - DefaultValuePipe, - ParseIntPipe, } from '@nestjs/common'; import { PermitService } from './permit.service'; import { ExceptionDto } from '../../common/exception/exception.dto'; @@ -32,15 +30,12 @@ import { ReadFileDto } from '../common/dto/response/read-file.dto'; import { Roles } from 'src/common/decorator/roles.decorator'; import { Role } from 'src/common/enum/roles.enum'; import { IDP } from 'src/common/enum/idp.enum'; -import { - IPaginationMeta, - IPaginationOptions, -} from 'src/common/interface/pagination.interface'; -import { PaginationDto } from 'src/common/class/pagination'; -import { LessThenPipe } from 'src/common/class/customs.transform'; +import { PaginationDto } from 'src/common/dto/paginate/pagination'; import { PermitHistoryDto } from './dto/response/permit-history.dto'; import { ResultDto } from './dto/response/result.dto'; import { VoidPermitDto } from './dto/request/void-permit.dto'; +import { ApiPaginatedResponse } from 'src/common/decorator/api-paginate-response'; +import { PageOptionsDto } from 'src/common/dto/paginate/page-options'; @ApiBearerAuth() @ApiTags('Permit') @@ -74,19 +69,6 @@ export class PermitController { return this.permitService.create(createPermitDto, currentUser); } - @ApiOkResponse({ - description: 'The Permit Resource', - type: ReadPermitDto, - isArray: true, - }) - @Roles(Role.READ_PERMIT) - @Get() - async get( - @Query('permitNumber') permitNumber: string, - ): Promise { - return this.permitService.findByPermitNumber(permitNumber); - } - @ApiOkResponse({ description: 'The Permit Resource to get revision and payment history.', type: PermitHistoryDto, @@ -108,60 +90,46 @@ export class PermitController { */ @ApiQuery({ name: 'companyId', required: true }) @ApiQuery({ name: 'expired', required: false, example: 'true' }) - @ApiQuery({ name: 'page', required: false, example: '1' }) - @ApiQuery({ name: 'limit', required: false, example: '10' }) + @ApiPaginatedResponse(ReadPermitDto) @Roles(Role.READ_PERMIT) - @Get('user') - async getPaginatedUserPermit( + @Get() + async getPermit( @Req() request: Request, @Query('companyId') companyId: number, @Query('expired') expired: string, - @Query('page', new DefaultValuePipe(1), ParseIntPipe) page = 1, - @Query('limit', new DefaultValuePipe(10), ParseIntPipe, LessThenPipe) - limit = 10, - ): Promise> { - const options: IPaginationOptions = { - limit, - page, - }; - + @Query() pageOptionsDto: PageOptionsDto, + ): Promise> { const currentUser = request.user as IUserJWT; const userGuid = currentUser.identity_provider === IDP.BCEID ? currentUser.bceid_user_guid : null; return await this.permitService.findUserPermit( - options, + pageOptionsDto, userGuid, companyId, expired, ); } - @ApiOkResponse({ - description: 'The Search Permit Resource', - type: PaginationDto, - isArray: true, - }) /** * @Query searchColumn: Key to search a permit. ex: plate * @Query searchString: Value of key. ex: AB123D * The above example will search for a permit where plate is AB123D. */ + @ApiPaginatedResponse(ReadPermitDto) @Roles(Role.STAFF) @Get('ppc/search') async getPermitData( @Query('searchColumn') searchColumn: string, @Query('searchString') searchString: string, - @Query('page', new DefaultValuePipe(1), ParseIntPipe) page = 1, - @Query('limit', new DefaultValuePipe(10), ParseIntPipe, LessThenPipe) - limit = 10, - ): Promise> { - const options: IPaginationOptions = { - limit, - page, - }; - return this.permitService.findPermit(options, searchColumn, searchString); + @Query() pageOptionsDto: PageOptionsDto, + ): Promise> { + return this.permitService.findPermit( + pageOptionsDto, + searchColumn, + searchString, + ); } @ApiCreatedResponse({ diff --git a/vehicles/src/modules/permit/permit.service.ts b/vehicles/src/modules/permit/permit.service.ts index f60d06e69..2bbd80899 100644 --- a/vehicles/src/modules/permit/permit.service.ts +++ b/vehicles/src/modules/permit/permit.service.ts @@ -21,12 +21,7 @@ import { Response } from 'express'; import { ReadFileDto } from '../common/dto/response/read-file.dto'; import { PermitStatus } from 'src/common/enum/permit-status.enum'; import { Receipt } from '../payment/entities/receipt.entity'; -import { - IPaginationMeta, - IPaginationOptions, -} from 'src/common/interface/pagination.interface'; -import { PaginationDto } from 'src/common/class/pagination'; -import { paginate } from 'src/common/helper/paginate'; +import { PaginationDto } from 'src/common/dto/paginate/pagination'; import { PermitHistoryDto } from './dto/response/permit-history.dto'; import { ApplicationStatus } from 'src/common/enum/application-status.enum'; import { ApplicationService } from './application.service'; @@ -55,6 +50,8 @@ import { Cache } from 'cache-manager'; import { PermitIssuedBy } from '../../common/enum/permit-issued-by.enum'; import { getPaymentCodeFromCache } from '../../common/helper/payment.helper'; import { PaymentMethodType } from 'src/common/enum/payment-method-type.enum'; +import { PageOptionsDto } from 'src/common/dto/paginate/page-options'; +import { PageMetaDto } from 'src/common/dto/paginate/page-meta'; @Injectable() export class PermitService { @@ -184,14 +181,16 @@ export class PermitService { } async findPermit( - options: IPaginationOptions, + pageOptionsDto: PageOptionsDto, searchColumn: string, searchString: string, - ): Promise> { + ): Promise> { const permits = this.permitRepository .createQueryBuilder('permit') .innerJoinAndSelect('permit.permitData', 'permitData') - .where('permit.permitNumber IS NOT NULL'); + .where('permit.permitNumber IS NOT NULL') + .skip(pageOptionsDto.skip) + .take(pageOptionsDto.take); if (searchColumn.toLowerCase() === 'plate') { permits.andWhere( `JSON_VALUE(permitData.permitData, '$.vehicleDetails.plate') like '%${searchString}%'`, @@ -214,21 +213,18 @@ export class PermitService { if (searchColumn.toLowerCase() === 'applicationnumber') { permits.andWhere(`permit.applicationNumber like '%${searchString}%'`); } - const permit: PaginationDto = await paginate( - permits, - options, - ); + + const totalItems = await permits.getCount(); + const { entities } = await permits.getRawAndEntities(); + + const pageMetaDto = new PageMetaDto({ totalItems, pageOptionsDto }); + const readPermitDto: ReadPermitDto[] = await this.classMapper.mapArrayAsync( - permit.items, + entities, Permit, ReadPermitDto, ); - const readPermitDtoItems: PaginationDto = - new PaginationDto( - readPermitDto, - permit.meta, - ); - return readPermitDtoItems; + return new PaginationDto(readPermitDto, pageMetaDto); } /** @@ -239,11 +235,11 @@ export class PermitService { * */ public async findUserPermit( - options: IPaginationOptions, + pageOptionsDto: PageOptionsDto, userGUID: string, companyId: number, expired: string, - ): Promise> { + ): Promise> { const permits = this.permitRepository .createQueryBuilder('permit') .innerJoinAndSelect('permit.permitData', 'permitData') @@ -265,23 +261,21 @@ export class PermitService { activeStatus: PermitStatus.ISSUED, expiryDate: new Date(), }, - ); + ) + .skip(pageOptionsDto.skip) + .take(pageOptionsDto.take); + + const totalItems = await permits.getCount(); + const { entities } = await permits.getRawAndEntities(); + + const pageMetaDto = new PageMetaDto({ totalItems, pageOptionsDto }); - const permit: PaginationDto = await paginate( - permits, - options, - ); const readPermitDto: ReadPermitDto[] = await this.classMapper.mapArrayAsync( - permit.items, + entities, Permit, ReadPermitDto, ); - const readPermitDtoItems: PaginationDto = - new PaginationDto( - readPermitDto, - permit.meta, - ); - return readPermitDtoItems; + return new PaginationDto(readPermitDto, pageMetaDto); } /**