Skip to content

Commit

Permalink
Added Review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
gchauhan-aot committed Dec 31, 2024
1 parent 743c883 commit 26fc97f
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 148 deletions.
174 changes: 171 additions & 3 deletions vehicles/src/common/helper/validate-loa.helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ReadLoaDto } from 'src/modules/special-auth/dto/response/read-loa.dto';
import { PermitType } from '../enum/permit-type.enum';
import { Loas } from '../interface/permit.template.interface';
import { Loas, PermitData } from '../interface/permit.template.interface';
import { Permit } from 'src/modules/permit-application-payment/permit/entities/permit.entity';
import * as dayjs from 'dayjs';
import { In, QueryRunner } from 'typeorm';
import { LoaDetail } from 'src/modules/special-auth/entities/loa-detail.entity';
import { Mapper } from '@automapper/core';
import { UnprocessableEntityException } from '@nestjs/common';

export const isVehicleTypeValid = (
permitVehicleType: string,
Expand Down Expand Up @@ -36,7 +40,171 @@ export const isValidDateForLoa = (
const { startDate: permitStartDate, expiryDate: permitExpiryDate } =
permit.permitData;
return (
dayjs(startDate).isBefore(permitStartDate, 'day') &&
(expiryDate ? dayjs(expiryDate).isAfter(permitExpiryDate, 'day') : true)
isStartDateValid(startDate, permitStartDate) &&
isEndDateValid(expiryDate, permitExpiryDate)
);
};

export const isStartDateValid = (
startDate: string,
permitStartDate: string,
): boolean => {
return (
dayjs(startDate).isBefore(permitStartDate, 'day') ||
dayjs(startDate).isSame(permitStartDate, 'day')
);
};

export const isEndDateValid = (
expiryDate: string,
permitExpiryDate: string,
): boolean => {
return expiryDate
? dayjs(expiryDate).isAfter(permitExpiryDate, 'day') ||
dayjs(expiryDate).isSame(permitExpiryDate, 'day')
: true;
};
export const isValidLoa = async (
permit: Permit,
queryRunner: QueryRunner,
mapper: Mapper,
) => {
const { companyId } = permit.company;
const permitData = JSON.parse(permit.permitData.permitData) as PermitData;
const { vehicleId: permitVehicleId, vehicleType: permitVehicleType } =
permitData.vehicleDetails;
if (permitData.loas) {
const loaNumbers = permitData.loas.map((loa) => loa.loaNumber);
const readLoaDto = await findLoas(
companyId,
loaNumbers,
queryRunner,
mapper,
);

// Validate LOA details and permit data against database entries
validateLoaDetails(readLoaDto, permit, permitVehicleId, permitVehicleType);

// validate LoA snapshot in permit Data
validatePermitDataAgainstLoas(
permitData,
permit,
permitVehicleId,
permitVehicleType,
);
}
};
export const validateLoaDetails = (
readLoaDtos: ReadLoaDto[],
permit: Permit,
permitVehicleId: string,
permitVehicleType: string,
) => {
for (const readLoaDto of readLoaDtos) {
const {
powerUnits: loaPowerUnits,
trailers: loaTrailers,
loaPermitType: loaPermitTypes,
} = readLoaDto;
if (!isValidDateForLoa(readLoaDto, permit)) {
console.log('ReadLoADetails: ', readLoaDto);
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA with invalid date(s).`,
);
}
if (
!isVehicleTypeValid(
permitVehicleType,
permitVehicleId,
loaPowerUnits,
loaTrailers,
)
) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA with invalid vehicle(s).`,
);
}
if (!isPermitTypeValid(permit.permitType, loaPermitTypes)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} ha LoA with invalid permitType.`,
);
}
}
};

export const validatePermitDataAgainstLoas = (
permitData: PermitData,
permit: Permit,
permitVehicleId: string,
permitVehicleType: string,
) => {
for (const loa of permitData.loas) {
const permitLoaPowerUnits = loa.powerUnits;
const permitLoaTrailers = loa.trailers;
const permitTypesLoa = loa.loaPermitType;
if (!isValidDateForLoa(loa, permit)) {
console.log('loa: ', loa);
console.log('permit: ', permit);

throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid date(s).`,
);
}

if (
!isVehicleTypeValid(
permitVehicleType,
permitVehicleId,
permitLoaPowerUnits,
permitLoaTrailers,
)
) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid vehicle(s).`,
);
}
if (!isPermitTypeValid(permit.permitType, permitTypesLoa)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid permitType.`,
);
}
}
};

/**
* Retrieves a single LOA (Letter of Authorization) detail for a specified company.
*
* Steps:
* 1. Fetches the LOA detail from the repository based on company ID and LOA Number.
* 2. Ensures the fetched LOA detail is active.
* 3. Includes relations (company, loaVehicles, loaPermitTypes) in the query.
*
* @param {number} companyId - ID of the company for which to fetch the LOA detail.
* @param {number} loaId - ID of the LOA to be fetched.
* @returns {Promise<LoaDetail>} - Returns a Promise that resolves to the LOA detail.
*/
export const findLoas = async (
companyId: number,
loaNumbers: number[],
queryRunner: QueryRunner,
mapper: Mapper,
): Promise<ReadLoaDto[]> => {
// Fetch initial active LOA details
const loaDetails = await queryRunner.manager.find(LoaDetail, {
where: {
loaNumber: In(loaNumbers),
isActive: true,
company: { companyId },
},
relations: ['company', 'loaVehicles', 'loaPermitTypes'],
});
const readLoaDto = await mapper.mapArrayAsync(
loaDetails,
LoaDetail,
ReadLoaDto,
{
extraArgs: () => ({ companyId: companyId }),
},
);
return readLoaDto;
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { PaymentMethodType } from './entities/payment-method-type.entity';
import { PaymentReportService } from './payment-report.service';
import { Permit } from '../permit/entities/permit.entity';
import { CfsTransactionDetail } from './entities/cfs-transaction.entity';
import { LoaDetail } from 'src/modules/special-auth/entities/loa-detail.entity';

@Module({
imports: [
Expand All @@ -23,7 +22,6 @@ import { LoaDetail } from 'src/modules/special-auth/entities/loa-detail.entity';
PaymentCardType,
PaymentMethodType,
CfsTransactionDetail,
LoaDetail,
]),
],
controllers: [PaymentController],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,7 @@ import {
import { SpecialAuth } from 'src/modules/special-auth/entities/special-auth.entity';
import { TIMEZONE_PACIFIC } from 'src/common/constants/api.constant';
import { PermitData } from 'src/common/interface/permit.template.interface';
import { LoaDetail } from 'src/modules/special-auth/entities/loa-detail.entity';
import {
isPermitTypeValid,
isValidDateForLoa,
isVehicleTypeValid,
} from 'src/common/helper/validate-loa.helper';
import { ReadLoaDto } from 'src/modules/special-auth/dto/response/read-loa.dto';
import { isValidLoa } from 'src/common/helper/validate-loa.helper';

@Injectable()
export class PaymentService {
Expand All @@ -95,8 +89,6 @@ export class PaymentService {
private paymentMethodTypeRepository: Repository<PaymentMethodType>,
@InjectRepository(PaymentCardType)
private paymentCardTypeRepository: Repository<PaymentCardType>,
@InjectRepository(LoaDetail)
private loaDetailRepository: Repository<LoaDetail>,
@InjectMapper() private readonly classMapper: Mapper,
@Inject(CACHE_MANAGER)
private readonly cacheManager: Cache,
Expand Down Expand Up @@ -346,7 +338,7 @@ export class PaymentService {
) as PermitData;
// If application includes LoAs then validate Loa data.
if (permitData.loas) {
await this.isValidLoa(application);
await isValidLoa(application, queryRunner, this.classMapper);
}
}
const totalTransactionAmount = await this.validateApplicationAndPayment(
Expand Down Expand Up @@ -904,137 +896,4 @@ export class PaymentService {
})),
) as PermitHistoryDto[];
}

async isValidLoa(permit: Permit): Promise<void> {
const { companyId } = permit.company;
const permitData = JSON.parse(permit.permitData.permitData) as PermitData;
const { vehicleId: permitVehicleId, vehicleType: permitVehicleType } =
permitData.vehicleDetails;
const loaNumbers = permitData.loas.map((loa) => loa.loaNumber);
const readLoaDto = await this.findLoas(companyId, loaNumbers);

// Validate LOA details and permit data against database entries
this.validateLoaDetails(
readLoaDto,
permit,
permitVehicleId,
permitVehicleType,
);

// validate LoA snapshot in permit Data
this.validatePermitDataAgainstLoas(
permitData,
permit,
permitVehicleId,
permitVehicleType,
);
}
private validateLoaDetails(
readLoaDtos: ReadLoaDto[],
permit: Permit,
permitVehicleId: string,
permitVehicleType: string,
) {
for (const readLoaDto of readLoaDtos) {
const loaPowerUnits = readLoaDto.powerUnits;
const loaTrailers = readLoaDto.trailers;
const loaPermitTypes = readLoaDto.loaPermitType;
if (!isValidDateForLoa(readLoaDto, permit)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA with invalid date(s).`,
);
}
if (
!isVehicleTypeValid(
permitVehicleType,
permitVehicleId,
loaPowerUnits,
loaTrailers,
)
) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA with invalid vehicle(s).`,
);
}
if (!isPermitTypeValid(permit.permitType, loaPermitTypes)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} ha LoA with invalid permitType.`,
);
}
}
}

private validatePermitDataAgainstLoas(
permitData: PermitData,
permit: Permit,
permitVehicleId: string,
permitVehicleType: string,
) {
for (const loa of permitData.loas) {
const permitLoaPowerUnits = loa.powerUnits;
const permitLoaTrailers = loa.trailers;
const permitTypesLoa = loa.loaPermitType;
if (!isValidDateForLoa(loa, permit)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid date(s).`,
);
}

if (
!isVehicleTypeValid(
permitVehicleType,
permitVehicleId,
permitLoaPowerUnits,
permitLoaTrailers,
)
) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid vehicle(s).`,
);
}
if (!isPermitTypeValid(permit.permitType, permitTypesLoa)) {
throw new UnprocessableEntityException(
`${permit.applicationNumber} has LoA snapshot with invalid permitType.`,
);
}
}
}

/**
* Retrieves a single LOA (Letter of Authorization) detail for a specified company.
*
* Steps:
* 1. Fetches the LOA detail from the repository based on company ID and LOA Number.
* 2. Ensures the fetched LOA detail is active.
* 3. Includes relations (company, loaVehicles, loaPermitTypes) in the query.
*
* @param {number} companyId - ID of the company for which to fetch the LOA detail.
* @param {number} loaId - ID of the LOA to be fetched.
* @returns {Promise<LoaDetail>} - Returns a Promise that resolves to the LOA detail.
*/
@LogAsyncMethodExecution()
async findLoas(
companyId: number,
loaNumbers: number[],
): Promise<ReadLoaDto[]> {
// Fetch initial active LOA details
const loaDetails = await this.loaDetailRepository.find({
where: {
loaNumber: In(loaNumbers),
isActive: true,
company: { companyId },
},
relations: ['company', 'loaVehicles', 'loaPermitTypes'],
});

const readLoaDto = await this.classMapper.mapArrayAsync(
loaDetails,
LoaDetail,
ReadLoaDto,
{
extraArgs: () => ({ companyId: companyId }),
},
);
return readLoaDto;
}
}

0 comments on commit 26fc97f

Please sign in to comment.