Skip to content

Commit

Permalink
ORV2-2073 Shopping Cart APIs (#1320)
Browse files Browse the repository at this point in the history
Co-authored-by: praju-aot <[email protected]>
  • Loading branch information
krishnan-aot and praju-aot authored Apr 8, 2024
1 parent 7d4b130 commit ba076e0
Show file tree
Hide file tree
Showing 14 changed files with 698 additions and 31 deletions.
1 change: 0 additions & 1 deletion database/mssql/scripts/versions/revert/v_26_ddl_revert.sql
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,3 @@ ELSE BEGIN
PRINT 'The database update failed'
END
GO

2 changes: 2 additions & 0 deletions vehicles/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { CompanySuspendModule } from './modules/company-user-management/company-
import { PermitModule } from './modules/permit-application-payment/permit/permit.module';
import { ApplicationModule } from './modules/permit-application-payment/application/application.module';
import { PaymentModule } from './modules/permit-application-payment/payment/payment.module';
import { ShoppingCartModule } from './modules/shopping-cart/shopping-cart.module';

const envPath = path.resolve(process.cwd() + '/../');

Expand Down Expand Up @@ -91,6 +92,7 @@ const envPath = path.resolve(process.cwd() + '/../');
PendingUsersModule,
AuthModule,
PaymentModule,
ShoppingCartModule,
ApplicationModule, //! Application Module should be imported before PermitModule to avoid URI conflict
PermitModule,
FeatureFlagsModule,
Expand Down
37 changes: 37 additions & 0 deletions vehicles/src/common/helper/permit-application.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import { callDatabaseSequence } from './database.helper';
import { PermitApplicationOrigin as PermitApplicationOriginEnum } from '../enum/permit-application-origin.enum';
import { PermitApprovalSource as PermitApprovalSourceEnum } from '../enum/permit-approval-source.enum';
import { randomInt } from 'crypto';
import { Directory } from '../enum/directory.enum';
import { doesUserHaveAuthGroup } from './auth.helper';
import {
IDIR_USER_AUTH_GROUP_LIST,
UserAuthGroup,
} from '../enum/user-auth-group.enum';
import { PPC_FULL_TEXT } from '../constants/api.constant';
import { User } from '../../modules/company-user-management/users/entities/user.entity';

/**
* Fetches and resolves various types of names associated with a permit using cache.
Expand Down Expand Up @@ -189,3 +197,32 @@ export const generatePermitNumber = async (
const permitNumber = `P${approvalSourceId}-${sequence}-${randomNumber}${revision}`;
return permitNumber;
};

/**
* Determines the appropriate display name for the applicant based on their directory type and the
* current user's authorization group.
* - For users from the IDIR directory, it returns the user's username if the current user has the
* correct authorization group. Otherwise, it returns a predefined full text constant.
* - For users from other directories, it returns the user's first and last name, concatenated.
* @param applicationOwner The user object representing the owner of the application.
* @param currentUserAuthGroup The authorization group of the current user.
* @returns The display name of the application owner as a string.
*/
export const getApplicantDisplay = (
applicationOwner: User,
currentUserAuthGroup: UserAuthGroup,
): string => {
if (applicationOwner?.directory === Directory.IDIR) {
if (
doesUserHaveAuthGroup(currentUserAuthGroup, IDIR_USER_AUTH_GROUP_LIST)
) {
return applicationOwner?.userName;
} else {
return PPC_FULL_TEXT;
}
} else {
const firstName = applicationOwner?.userContact?.firstName ?? '';
const lastName = applicationOwner?.userContact?.lastName ?? '';
return (firstName + ' ' + lastName).trim();
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -196,35 +196,6 @@ export class ApplicationService {
});
}

private async findOneWithSuccessfulTransaction(
applicationId: string,
companyId?: number,
): Promise<Permit> {
const permitQB = this.permitRepository.createQueryBuilder('permit');
permitQB
.leftJoinAndSelect('permit.company', 'company')
.innerJoinAndSelect('permit.permitData', 'permitData')
.innerJoinAndSelect('permit.permitTransactions', 'permitTransactions')
.innerJoinAndSelect('permitTransactions.transaction', 'transaction')
.innerJoinAndSelect('transaction.receipt', 'receipt')
.leftJoinAndSelect('permit.applicationOwner', 'applicationOwner')
.leftJoinAndSelect(
'applicationOwner.userContact',
'applicationOwnerContact',
)
.where('permit.permitId = :permitId', {
permitId: applicationId,
})
.andWhere('receipt.receiptNumber IS NOT NULL');

if (companyId) {
permitQB.andWhere('company.companyId = :companyId', {
companyId: companyId,
});
}
return await permitQB.getOne();
}

/**
* Finds multiple permits by application IDs or a single transaction ID with successful transactions,
* optionally filtering by companyId.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class ReadPermitDto {

@AutoMap()
@ApiProperty({
description: 'Satus of Permit/Permit Application',
description: 'Status of Permit/Permit Application',
example: PermitStatus.ISSUED,
required: false,
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AutoMap } from '@automapper/classes';
import { ApiProperty } from '@nestjs/swagger';
import { ArrayMinSize, IsNumberString } from 'class-validator';

/**
* DTO (Data Transfer Object) for creating a shopping cart.
* It includes the necessary properties and validations for the creation process.
*
* @property {string[]} applicationIds - Application Ids to be added to the cart. Should be an array of number strings without symbols.
*/
export class AddToShoppingCartDto {
@AutoMap()
@ApiProperty({
description: 'Application Ids to be added to the cart.',
isArray: true,
type: String,
example: ['74'],
})
@ArrayMinSize(1)
@IsNumberString({ no_symbols: true }, { each: true })
applicationIds: string[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsInt, IsPositive } from 'class-validator';

export class CompanyIdPathParamDto {
@ApiProperty({
description: `Id of the company the cart belongs to.`,
example: 74,
})
@IsInt()
@IsPositive()
@Type(() => Number)
companyId: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { AddToShoppingCartDto } from './add-to-shopping-cart.dto';

export class UpdateShoppingCartDto extends AddToShoppingCartDto {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { AutoMap } from '@automapper/classes';
import { ApiProperty } from '@nestjs/swagger';
import { ApplicationStatus } from '../../../../common/enum/application-status.enum';
import { PermitType } from '../../../../common/enum/permit-type.enum';

export class ReadShoppingCartDto {
@AutoMap()
@ApiProperty({
description: 'Id of the company requesting the permit.',
example: 74,
})
companyId: number;

@AutoMap()
@ApiProperty({
description: 'Id of the application.',
example: 74,
})
applicationId: string;

@AutoMap()
@ApiProperty({
enum: PermitType,
description: 'The permit type abbreviation.',
example: PermitType.TERM_OVERSIZE,
})
permitType: PermitType;

@AutoMap()
@ApiProperty({
example: 'A2-00000002-120',
description: 'Unique formatted permit application number.',
})
applicationNumber: string;

@AutoMap()
@ApiProperty({
description: 'Status of Permit/Permit Application',
example: ApplicationStatus.IN_CART,
required: false,
})
permitStatus: ApplicationStatus.IN_CART;

@AutoMap()
@ApiProperty({
description: 'Application updated Date and Time.',
})
updatedDateTime: string;

@AutoMap()
@ApiProperty({
description: 'Name of the applicant',
example: 'John Smith',
})
applicant: string;

@AutoMap()
@ApiProperty({
description: 'The userGUID of the applicant',
example: 'S822OKE22LK',
})
applicantGUID: string;

@AutoMap()
@ApiProperty({
description: 'The vehicle plate',
example: 'S822OK',
})
plate: string;

@AutoMap()
@ApiProperty({
description: 'The permit start date.',
example: '2023-06-05T19:12:22Z',
})
startDate: string;

@AutoMap()
@ApiProperty({
description: 'The permit start date.',
example: '2023-07-04T19:12:22Z',
})
expiryDate: string;

@ApiProperty({
description: 'The permit fee',
example: 200,
})
fee: number;
}
5 changes: 5 additions & 0 deletions vehicles/src/modules/shopping-cart/dto/response/result.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class ResultDto {
success: string[];

failure: string[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
Mapper,
createMap,
forMember,
mapFrom,
mapWithArguments,
} from '@automapper/core';
import { AutomapperProfile, InjectMapper } from '@automapper/nestjs';
import { Injectable } from '@nestjs/common';

import { UserAuthGroup } from '../../../common/enum/user-auth-group.enum';
import { getApplicantDisplay } from '../../../common/helper/permit-application.helper';
import { Permit as Application } from '../../permit-application-payment/permit/entities/permit.entity';
import { ReadShoppingCartDto } from '../dto/response/read-shopping-cart.dto';
import { PermitData } from '../../../common/interface/permit.template.interface';

@Injectable()
export class ShoppingCartProfile extends AutomapperProfile {
constructor(@InjectMapper() mapper: Mapper) {
super(mapper);
}

override get profile() {
return (mapper: Mapper) => {
createMap(
mapper,
Application,
ReadShoppingCartDto,
forMember(
(d) => d.companyId,
mapWithArguments((_s, { companyId }) => companyId),
),
// permitId
forMember(
(d) => d.applicationId,
mapFrom((s) => s?.permitId),
),
forMember(
(d) => d.applicant,
mapWithArguments((s, { currentUserAuthGroup }) => {
return getApplicantDisplay(
s.applicationOwner,
currentUserAuthGroup as UserAuthGroup,
);
}),
),
forMember(
(d) => d.applicantGUID,
mapFrom((s) => s?.applicationOwner?.userGUID),
),
forMember(
(d) => d.fee,
mapFrom((s) => {
const parsedPermitData = JSON.parse(
s?.permitData?.permitData,
) as PermitData;
return +parsedPermitData?.feeSummary;
}),
),
forMember(
(d) => d.plate,
mapFrom((s) => s?.permitData?.plate),
),
forMember(
(d) => d.startDate,
mapFrom((s) => s?.permitData?.startDate),
),
forMember(
(d) => d.expiryDate,
mapFrom((s) => s?.permitData?.expiryDate),
),
);
};
}
}
Loading

0 comments on commit ba076e0

Please sign in to comment.