diff --git a/vehicles/src/common/enum/payment-method-type.enum.ts b/vehicles/src/common/enum/payment-method-type.enum.ts index 4e1aa8803..21cf17684 100644 --- a/vehicles/src/common/enum/payment-method-type.enum.ts +++ b/vehicles/src/common/enum/payment-method-type.enum.ts @@ -25,11 +25,17 @@ export type PaymentMethodTypeReport = export type CfsPaymentMethodType = Extract< PaymentMethodType, - PaymentMethodType.ICEPAY | PaymentMethodType.CASH | PaymentMethodType.CHEQUE + | PaymentMethodType.ICEPAY + | PaymentMethodType.CASH + | PaymentMethodType.CHEQUE + | PaymentMethodType.GA + | PaymentMethodType.POS >; export const CfsPaymentMethodType = { [PaymentMethodType.ICEPAY]: PaymentMethodType.ICEPAY, [PaymentMethodType.CASH]: PaymentMethodType.CASH, [PaymentMethodType.CHEQUE]: PaymentMethodType.CHEQUE, + [PaymentMethodType.GA]: PaymentMethodType.GA, + [PaymentMethodType.POS]: PaymentMethodType.POS, } as const; diff --git a/vehicles/src/common/helper/common.helper.ts b/vehicles/src/common/helper/common.helper.ts index 44e5f605a..b7f1ed268 100644 --- a/vehicles/src/common/helper/common.helper.ts +++ b/vehicles/src/common/helper/common.helper.ts @@ -1,3 +1,8 @@ +import { Cache } from 'cache-manager'; +import { CacheKey } from '../enum/cache-key.enum'; +import { getFromCache } from './cache.helper'; +import { FeatureFlagValue } from '../enum/feature-flag-value.enum'; + /** * Evaluates the given predicate and returns the value if the predicate is true or the value is not null, otherwise returns undefined. * @@ -19,3 +24,27 @@ export const undefinedSubstitution = ( return result; }; + +/** + * Determines if a feature is enabled by checking the value of a feature flag in the cache. + * + * @param {Cache} cacheManager - The cache manager to retrieve the feature flag value. + * @param {string} featureFlag - The feature flag to be evaluated. + * @returns {Promise} - A promise that resolves to true if the feature flag is enabled, otherwise false. + */ +export const isFeatureEnabled = async ( + cacheManager: Cache, + featureFlag: string, +): Promise => { + const featureFlagValue = (await getFromCache( + cacheManager, + CacheKey.FEATURE_FLAG_TYPE, + featureFlag, + )) as FeatureFlagValue; + + if (featureFlagValue !== FeatureFlagValue.ENABLED) { + return false; + } + + return true; +}; diff --git a/vehicles/src/common/helper/exception.helper.ts b/vehicles/src/common/helper/exception.helper.ts index c28381f40..24ab7fb60 100644 --- a/vehicles/src/common/helper/exception.helper.ts +++ b/vehicles/src/common/helper/exception.helper.ts @@ -1,6 +1,11 @@ -import { HttpStatus, UnprocessableEntityException } from '@nestjs/common'; +import { + BadRequestException, + HttpStatus, + UnprocessableEntityException, +} from '@nestjs/common'; import { ExceptionDto } from '../exception/exception.dto'; import { ValidationExceptionDto } from '../exception/validation.exception.dto'; +import { BadRequestExceptionDto } from '../exception/badRequestException.dto'; export const throwUnprocessableEntityException = ( message: string, @@ -17,3 +22,16 @@ export const throwUnprocessableEntityException = ( ] as ValidationExceptionDto[], } as ExceptionDto); }; + +export const throwBadRequestException = (field: string, message: string[]) => { + throw new BadRequestException({ + message: 'Bad Request', + status: HttpStatus.BAD_REQUEST, + error: [ + { + field: field, + message: message, + }, + ] as BadRequestExceptionDto[], + } as ExceptionDto); +}; diff --git a/vehicles/src/modules/permit-application-payment/payment/payment.controller.ts b/vehicles/src/modules/permit-application-payment/payment/payment.controller.ts index 3e3b9decd..36c48d234 100644 --- a/vehicles/src/modules/permit-application-payment/payment/payment.controller.ts +++ b/vehicles/src/modules/permit-application-payment/payment/payment.controller.ts @@ -18,6 +18,7 @@ import { ApiOkResponse, ApiQuery, ApiTags, + ApiUnprocessableEntityResponse, } from '@nestjs/swagger'; import { ExceptionDto } from '../../../common/exception/exception.dto'; import { PaymentService } from './payment.service'; @@ -49,6 +50,10 @@ import { Role } from '../../../common/enum/roles.enum'; description: 'The Payment Api Internal Server Error Response', type: ExceptionDto, }) +@ApiUnprocessableEntityResponse({ + description: 'The Payment Entity could not be processed.', + type: ExceptionDto, +}) export class PaymentController { constructor( private readonly paymentService: PaymentService, diff --git a/vehicles/src/modules/permit-application-payment/payment/payment.service.ts b/vehicles/src/modules/permit-application-payment/payment/payment.service.ts index e443d62a1..b50df5710 100644 --- a/vehicles/src/modules/permit-application-payment/payment/payment.service.ts +++ b/vehicles/src/modules/permit-application-payment/payment/payment.service.ts @@ -55,6 +55,13 @@ import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; import { CacheKey } from 'src/common/enum/cache-key.enum'; import { getFromCache } from '../../../common/helper/cache.helper'; +import { doesUserHaveAuthGroup } from '../../../common/helper/auth.helper'; +import { IDIR_USER_AUTH_GROUP_LIST } from '../../../common/enum/user-auth-group.enum'; +import { + throwBadRequestException, + throwUnprocessableEntityException, +} from '../../../common/helper/exception.helper'; +import { isFeatureEnabled } from '../../../common/helper/common.helper'; @Injectable() export class PaymentService { @@ -69,8 +76,6 @@ export class PaymentService { private paymentMethodTypeRepository: Repository, @InjectRepository(PaymentCardType) private paymentCardTypeRepository: Repository, - @InjectRepository(Permit) - private permitRepository: Repository, @InjectMapper() private readonly classMapper: Mapper, @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, @@ -244,6 +249,39 @@ export class PaymentService { createTransactionDto: CreateTransactionDto, nestedQueryRunner?: QueryRunner, ): Promise { + if ( + !doesUserHaveAuthGroup( + currentUser.orbcUserAuthGroup, + IDIR_USER_AUTH_GROUP_LIST, + ) && + createTransactionDto?.paymentMethodTypeCode !== + PaymentMethodTypeEnum.WEB && + createTransactionDto?.paymentMethodTypeCode !== + PaymentMethodTypeEnum.ACCOUNT + ) { + throwUnprocessableEntityException( + 'Invalid payment method type for the user', + ); + } else if ( + createTransactionDto?.paymentMethodTypeCode === + PaymentMethodTypeEnum.ACCOUNT && + !(await isFeatureEnabled(this.cacheManager, 'CREDIT-ACCOUNT')) + ) { + throwUnprocessableEntityException('Disabled feature'); + } + + if ( + (createTransactionDto?.paymentMethodTypeCode === + PaymentMethodTypeEnum.WEB || + createTransactionDto?.paymentMethodTypeCode === + PaymentMethodTypeEnum.POS) && + !createTransactionDto?.paymentCardTypeCode + ) { + throwBadRequestException('paymentCardTypeCode', [ + `paymentCardTypeCode is required when paymentMethodTypeCode is ${createTransactionDto?.paymentMethodTypeCode}`, + ]); + } + let readTransactionDto: ReadTransactionDto; const queryRunner = nestedQueryRunner || this.dataSource.createQueryRunner();