generated from bcgov/quickstart-openshift
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ORV2-1857 - Staff Suspend COmpany (#1200)
- Loading branch information
Showing
19 changed files
with
534 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
vehicles/src/common/constraint/suspend-comment.constraint.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { | ||
ValidatorConstraint, | ||
ValidatorConstraintInterface, | ||
ValidationArguments, | ||
} from 'class-validator'; | ||
import { SuspendActivity } from '../enum/suspend-activity.enum'; | ||
|
||
@ValidatorConstraint({ name: 'SuspendComment', async: false }) | ||
export class SuspendCommentConstraint implements ValidatorConstraintInterface { | ||
validate(comment: string | undefined, args: ValidationArguments) { | ||
const suspendAcitivity = ( | ||
args.object as { | ||
suspendAcitivity?: SuspendActivity; | ||
} | ||
).suspendAcitivity; // Access the searchString property from the same object | ||
|
||
// If SuspendActivity.SUSPEND_COMPANY, comment should exists | ||
if (suspendAcitivity === SuspendActivity.SUSPEND_COMPANY && !comment) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
defaultMessage() { | ||
return `Comment is required when activity type is ${SuspendActivity.SUSPEND_COMPANY}`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export enum SuspendActivity { | ||
SUSPEND_COMPANY = 'SUSPEND', | ||
UNSUSPEND_COMPANY = 'UNSUSPEND', | ||
} |
96 changes: 96 additions & 0 deletions
96
vehicles/src/modules/company-user-management/company-suspend/company-suspend.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { Controller, Get, Post, Body, Param, Req } from '@nestjs/common'; | ||
import { CompanySuspendService } from './company-suspend.service'; | ||
import { | ||
ApiTags, | ||
ApiBadRequestResponse, | ||
ApiNotFoundResponse, | ||
ApiMethodNotAllowedResponse, | ||
ApiInternalServerErrorResponse, | ||
ApiBearerAuth, | ||
ApiCreatedResponse, | ||
ApiOkResponse, | ||
} from '@nestjs/swagger'; | ||
import { ExceptionDto } from '../../../common/exception/exception.dto'; | ||
import { CreateCompanySuspendDto } from './dto/request/create-company-suspend.dto'; | ||
import { IUserJWT } from '../../../common/interface/user-jwt.interface'; | ||
import { ReadCompanySuspendActivityDto } from './dto/response/read-company-suspend-activity.dto'; | ||
import { Request } from 'express'; | ||
import { Roles } from '../../../common/decorator/roles.decorator'; | ||
import { Role } from '../../../common/enum/roles.enum'; | ||
|
||
@ApiTags('Company and User Management - Company Suspend') | ||
@ApiBadRequestResponse({ | ||
description: 'Bad Request Response', | ||
type: ExceptionDto, | ||
}) | ||
@ApiNotFoundResponse({ | ||
description: 'The Company Suspend Api Not Found Response', | ||
type: ExceptionDto, | ||
}) | ||
@ApiMethodNotAllowedResponse({ | ||
description: 'The Company Suspend Api Method Not Allowed Response', | ||
type: ExceptionDto, | ||
}) | ||
@ApiInternalServerErrorResponse({ | ||
description: 'The Company Suspend Api Internal Server Error Response', | ||
type: ExceptionDto, | ||
}) | ||
@ApiBearerAuth() | ||
@Controller('companies/:companyId/company-suspend') | ||
export class CompanySuspendController { | ||
constructor(private readonly companySuspendService: CompanySuspendService) {} | ||
|
||
/** | ||
* A POST method defined with the @Post() decorator and a route of /:companyId/suspend | ||
* that suspends a company based on the company ID provided. It also creates a record of | ||
* the suspension activity. | ||
* | ||
* @param createCompanySuspendDto The http request object containing the suspension details. | ||
* | ||
* @returns The details of the suspension activity with | ||
* response object {@link ReadCompanySuspendActivityDto} | ||
*/ | ||
@ApiCreatedResponse({ | ||
description: 'The Company Suspension Activity Resource', | ||
type: ReadCompanySuspendActivityDto, | ||
}) | ||
@Roles(Role.WRITE_SUSPEND) | ||
@Post('suspend') | ||
async suspendCompany( | ||
@Req() request: Request, | ||
@Param('companyId') companyId: number, | ||
@Body() createCompanySuspendDto: CreateCompanySuspendDto, | ||
): Promise<ReadCompanySuspendActivityDto> { | ||
const currentUser = request.user as IUserJWT; | ||
return await this.companySuspendService.suspendCompany( | ||
companyId, | ||
createCompanySuspendDto, | ||
currentUser, | ||
); | ||
} | ||
|
||
/** | ||
* A GET method defined with the @Get() decorator and a route of /:companyId/suspend | ||
* that retrieves all suspend activities by companyId. | ||
* | ||
* @param companyId The company Id. | ||
* | ||
* @returns The suspend activities with response object {@link ReadCompanySuspendActivityDto}. | ||
*/ | ||
@ApiOkResponse({ | ||
description: 'The Company Suspend Activity Resource', | ||
type: ReadCompanySuspendActivityDto, | ||
isArray: true, | ||
}) | ||
@Roles(Role.READ_SUSPEND) | ||
@Get('suspend') | ||
async findAllSuspendActivityByCompanyId( | ||
@Param('companyId') companyId: number, | ||
): Promise<ReadCompanySuspendActivityDto[]> { | ||
const suspendActivityList = | ||
await this.companySuspendService.findAllSuspendActivityByCompanyId( | ||
companyId, | ||
); | ||
return suspendActivityList; | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
vehicles/src/modules/company-user-management/company-suspend/company-suspend.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { CompanySuspendService } from './company-suspend.service'; | ||
import { CompanySuspendController } from './company-suspend.controller'; | ||
import { TypeOrmModule } from '@nestjs/typeorm'; | ||
import { CompanyModule } from '../company/company.module'; | ||
import { CompanySuspendProfile } from './profiles/company-suspend.profile'; | ||
import { CompanySuspendActivity } from './entities/company-suspend-activity.entity'; | ||
|
||
@Module({ | ||
imports: [TypeOrmModule.forFeature([CompanySuspendActivity]), CompanyModule], | ||
controllers: [CompanySuspendController], | ||
providers: [CompanySuspendService, CompanySuspendProfile], | ||
}) | ||
export class CompanySuspendModule {} |
150 changes: 150 additions & 0 deletions
150
vehicles/src/modules/company-user-management/company-suspend/company-suspend.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
import { BadRequestException, Injectable, Logger } from '@nestjs/common'; | ||
|
||
import { Mapper } from '@automapper/core'; | ||
import { InjectMapper } from '@automapper/nestjs'; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import { Repository, DataSource } from 'typeorm'; | ||
import { LogAsyncMethodExecution } from '../../../common/decorator/log-async-method-execution.decorator'; | ||
import { SuspendActivity } from '../../../common/enum/suspend-activity.enum'; | ||
import { DataNotFoundException } from '../../../common/exception/data-not-found.exception'; | ||
import { IUserJWT } from '../../../common/interface/user-jwt.interface'; | ||
import { Company } from '../company/entities/company.entity'; | ||
import { IdirUser } from '../users/entities/idir.user.entity'; | ||
import { CompanyService } from '../company/company.service'; | ||
import { CreateCompanySuspendDto } from './dto/request/create-company-suspend.dto'; | ||
import { ReadCompanySuspendActivityDto } from './dto/response/read-company-suspend-activity.dto'; | ||
import { CompanySuspendActivity } from './entities/company-suspend-activity.entity'; | ||
|
||
@Injectable() | ||
export class CompanySuspendService { | ||
private readonly logger = new Logger(CompanySuspendService.name); | ||
constructor( | ||
@InjectRepository(CompanySuspendActivity) | ||
private companySuspendRepository: Repository<CompanySuspendActivity>, | ||
@InjectMapper() private readonly classMapper: Mapper, | ||
private dataSource: DataSource, | ||
private readonly companyService: CompanyService, | ||
) {} | ||
|
||
/** | ||
* The update() method retrieves the entity from the database using the | ||
* Repository, maps the DTO object to the entity using the Mapper, sets some | ||
* additional properties on the entity, and saves it back to the database | ||
* using the Repository. It then retrieves the updated entity and returns it | ||
* in a DTO object. | ||
* | ||
* | ||
* @param companyId The company Id. | ||
* @param updateCompanyDto Request object of type {@link UpdateCompanyDto} for | ||
* updating a company. | ||
* @param directory Directory derived from the access token. | ||
* | ||
* @returns The company details as a promise of type {@link ReadCompanyDto} | ||
*/ | ||
@LogAsyncMethodExecution() | ||
async suspendCompany( | ||
companyId: number, | ||
createCompanySuspendDtonyDto: CreateCompanySuspendDto, | ||
currentUser: IUserJWT, | ||
): Promise<ReadCompanySuspendActivityDto> { | ||
let savedSuspendAcitivity: CompanySuspendActivity; | ||
const company = await this.companyService.findOne(companyId); | ||
|
||
if (!company) { | ||
throw new DataNotFoundException(); | ||
} | ||
const toBeSuspended: boolean = | ||
createCompanySuspendDtonyDto.suspendActivityType === | ||
SuspendActivity.SUSPEND_COMPANY; | ||
if (company.isSuspended === toBeSuspended) { | ||
throw new BadRequestException( | ||
`Company ${companyId} is already in ${company.isSuspended ? SuspendActivity.SUSPEND_COMPANY : SuspendActivity.UNSUSPEND_COMPANY} status`, | ||
); | ||
} | ||
|
||
const queryRunner = this.dataSource.createQueryRunner(); | ||
await queryRunner.connect(); | ||
await queryRunner.startTransaction(); | ||
try { | ||
const currentDateTime: Date = new Date(); | ||
|
||
await queryRunner.manager | ||
.createQueryBuilder() | ||
.update(Company) | ||
.set({ | ||
isSuspended: toBeSuspended, | ||
updatedUser: currentUser.userName, | ||
updatedDateTime: currentDateTime, | ||
updatedUserDirectory: currentUser.orbcUserDirectory, | ||
updatedUserGuid: currentUser.userGUID, | ||
}) | ||
.where('companyId = :companyId', { companyId: companyId }) | ||
.execute(); | ||
|
||
const suspendActivity: CompanySuspendActivity = | ||
new CompanySuspendActivity(); | ||
|
||
suspendActivity.companyId = companyId; | ||
suspendActivity.suspendActivityType = | ||
createCompanySuspendDtonyDto.suspendActivityType; | ||
suspendActivity.comment = createCompanySuspendDtonyDto.comment; | ||
suspendActivity.suspendActivityDateTime = currentDateTime; | ||
const idirUser = new IdirUser(); | ||
idirUser.userGUID = currentUser.userGUID; | ||
suspendActivity.idirUser = idirUser; | ||
suspendActivity.createdUser = currentUser.userName; | ||
suspendActivity.createdUserGuid = currentUser.userGUID; | ||
suspendActivity.createdUserDirectory = currentUser.orbcUserDirectory; | ||
suspendActivity.createdDateTime = currentDateTime; | ||
suspendActivity.updatedUser = currentUser.userName; | ||
suspendActivity.updatedUserGuid = currentUser.userGUID; | ||
suspendActivity.updatedUserDirectory = currentUser.orbcUserDirectory; | ||
suspendActivity.updatedDateTime = currentDateTime; | ||
|
||
savedSuspendAcitivity = await queryRunner.manager.save(suspendActivity); | ||
|
||
await queryRunner.commitTransaction(); | ||
} catch (error) { | ||
await queryRunner.rollbackTransaction(); | ||
this.logger.error(error); | ||
throw error; | ||
} finally { | ||
await queryRunner.release(); | ||
} | ||
|
||
const result = await this.classMapper.mapAsync( | ||
savedSuspendAcitivity, | ||
CompanySuspendActivity, | ||
ReadCompanySuspendActivityDto, | ||
); | ||
result.userName = currentUser.userName?.toUpperCase(); | ||
return result; | ||
} | ||
|
||
/** | ||
* The findAllSuspendActivityByCompanyId() method retrieves all suspend activities associated with a given company ID. | ||
* It queries the suspend activity repository for records matching the company ID and includes the relation to the IDIR user. | ||
* The results are then mapped from the CompanySuspendActivity entities to ReadCompanySuspendActivityDto objects for presentation. | ||
* | ||
* @param companyId The unique identifier of the company. | ||
* | ||
* @returns A promise containing an array of ReadCompanySuspendActivityDto objects representing the suspend activities for the specified company. | ||
*/ | ||
@LogAsyncMethodExecution() | ||
async findAllSuspendActivityByCompanyId( | ||
companyId: number, | ||
): Promise<ReadCompanySuspendActivityDto[]> { | ||
const suspendActivityDbResults = await this.companySuspendRepository.find({ | ||
where: { companyId: companyId }, | ||
relations: { | ||
idirUser: true, | ||
}, | ||
}); | ||
|
||
return await this.classMapper.mapArrayAsync( | ||
suspendActivityDbResults, | ||
CompanySuspendActivity, | ||
ReadCompanySuspendActivityDto, | ||
); | ||
} | ||
} |
Oops, something went wrong.