diff --git a/package-lock.json b/package-lock.json index 78613c0..a284832 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "backend-8tech", - "version": "4.1.4", + "version": "4.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "backend-8tech", - "version": "4.1.4", + "version": "4.1.5", "license": "UNLICENSED", "dependencies": { "@nestjs/common": "^9.4.3", diff --git a/package.json b/package.json index 489e2df..74d1071 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "backend-8tech", - "version": "4.1.4", + "version": "4.1.5", "description": "", "author": "8tech", "private": true, diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5a12ee1..99d4a75 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -109,9 +109,9 @@ enum Role { enum ContractStatus { PENDING - ONGOING ACCEPTED REJECTED + ONGOING COMPLETED } diff --git a/src/contract/contract.controller.ts b/src/contract/contract.controller.ts index 4e7470b..ad58b3f 100644 --- a/src/contract/contract.controller.ts +++ b/src/contract/contract.controller.ts @@ -9,8 +9,15 @@ import { Header, Param, Redirect, + Req, } from '@nestjs/common'; -import { ApiBearerAuth, ApiParam, ApiTags } from '@nestjs/swagger'; +import { + ApiBearerAuth, + ApiBody, + ApiParam, + ApiResponse, + ApiTags, +} from '@nestjs/swagger'; import { Roles } from '../auth/roles/role.decorator'; import { JwtAuthGuard } from '../auth/jwt/jwt-auth.guard'; import { RoleGuard } from '../auth/roles/role.guard'; @@ -43,7 +50,7 @@ export class ContractController { } @ApiBearerAuth() - @Roles(Role.USER) + @Roles(Role.RECRUITER) @UseGuards(JwtAuthGuard, RoleGuard) @Post('update') async updateContract(@Res() res, @Body() data: ContractUpdateDto) { @@ -55,7 +62,7 @@ export class ContractController { @Get('generate/:contractId') @ApiParam({ name: 'contractId', type: String }) - @Roles(Role.USER) + @Roles(Role.RECRUITER) @Header('Content-Type', 'application/pdf') async generateContract( @Res({ passthrough: true }) res, @@ -80,6 +87,8 @@ export class ContractController { @ApiBearerAuth() @Get('userId/:userId') + @Roles(Role.USER) + @UseGuards(JwtAuthGuard, RoleGuard) @ApiParam({ name: 'userId', type: String }) async getAllbyUserId(@Res() res, @Param('userId') userId: string) { console.info('#getAllbyUserId request incoming with: ', userId); @@ -91,6 +100,8 @@ export class ContractController { @ApiBearerAuth() @Get('jobId/:jobId') + @Roles(Role.RECRUITER) + @UseGuards(JwtAuthGuard, RoleGuard) @ApiParam({ name: 'jobId', type: String }) async getAllbyJobId(@Res() res, @Param('jobId') jobId: string) { console.info('#getAllbyJobId request incoming with: ', jobId); @@ -102,6 +113,8 @@ export class ContractController { @ApiBearerAuth() @Get('Id/:Id') + @Roles(Role.USER) + @UseGuards(JwtAuthGuard, RoleGuard) @ApiParam({ name: 'Id', type: String }) async getContractbyId(@Res() res, @Param('Id') Id: string) { console.info('#getContractbyId request incoming with: ', Id); @@ -110,6 +123,8 @@ export class ContractController { } @ApiBearerAuth() + @Roles(Role.USER) + @UseGuards(JwtAuthGuard, RoleGuard) @Post('paymentRequest') async createPaymentRequest( @Res() res, @@ -140,6 +155,8 @@ export class ContractController { } @ApiBearerAuth() + @Roles(Role.USER) + @UseGuards(JwtAuthGuard, RoleGuard) @Get('payoutLink/:contractId') @ApiParam({ name: 'contractId', type: String }) async createPayoutLink(@Res() res, @Param() params: any) { @@ -148,4 +165,26 @@ export class ContractController { await this.contractService.createPayout(params.contractId); return response; } + + @Roles(Role.RECRUITER) + @ApiBearerAuth() + @UseGuards(JwtAuthGuard, RoleGuard) + @ApiBody({ + type: Object, + description: 'it receive page, size like this: {page: 1, size: 5}', + }) + @ApiResponse({ + description: + 'it will return paginated contract that include the job vacancy info & payment', + }) + @Post('recruiterContractList') + async getRecruiterContractList(@Req() req, @Body() data: any) { + console.info('#getRecruiterContractList request incoming with: ', data); + const response = await this.contractService.getContractByCompanyId( + req.user.companyId, + data.page, + data.size, + ); + return response; + } } diff --git a/src/contract/contract.repository.ts b/src/contract/contract.repository.ts index 9a9e2a2..fecc3b0 100644 --- a/src/contract/contract.repository.ts +++ b/src/contract/contract.repository.ts @@ -1,4 +1,5 @@ -import { Injectable } from '@nestjs/common'; +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { pagination, returnablePaginated } from '../prisma/prisma.util'; import { PrismaService } from '../prisma/prisma.service'; import { Contract } from '@prisma/client'; @@ -20,7 +21,7 @@ export class ContractRepository { return this.prisma.contract.update({ data: contract, where: { - id: contract.id, + id, }, }); } @@ -70,4 +71,40 @@ export class ContractRepository { }, }); } + + async delete(id: any): Promise { + return this.prisma.contract.delete({ + where: { + id, + }, + }); + } + + async getContractListByCompanyId( + companyId: string, + page: number, + size: number, + ): Promise { + let res; + + try { + res = await this.prisma.contract.findMany({ + where: { + jobVacancy: { + company: { + id: companyId, + }, + }, + }, + include: { + payment: true, + jobVacancy: true, + }, + ...pagination(page, size), + }); + } catch (e) { + throw new HttpException({ prisma: e.message }, HttpStatus.BAD_REQUEST); + } + return returnablePaginated(res, res.length, page, size); + } } diff --git a/src/contract/contract.service.ts b/src/contract/contract.service.ts index a5b864e..37d2d36 100644 --- a/src/contract/contract.service.ts +++ b/src/contract/contract.service.ts @@ -67,6 +67,18 @@ export class ContractService { return await this.contractRepository.get(id); } + async getContractByCompanyId( + companyId: string, + page: number, + size: number, + ): Promise { + return await this.contractRepository.getContractListByCompanyId( + companyId, + page, + size, + ); + } + //Update Contract //#endregion diff --git a/src/users/user.controller.ts b/src/users/user.controller.ts index b62c820..fc1f12f 100644 --- a/src/users/user.controller.ts +++ b/src/users/user.controller.ts @@ -14,6 +14,8 @@ import { ApiBearerAuth, ApiBody, ApiCookieAuth, + ApiParam, + ApiResponse, ApiTags, } from '@nestjs/swagger'; import { UsersService } from './users.service'; @@ -134,6 +136,39 @@ export class UserController { } @ApiBearerAuth() + @ApiResponse({ + schema: { + example: { + status: true, + statusCode: 200, + data: { + data: [ + { + id: 'fc808550-b179-4657-a999-40795b0903d1', + title: 'This is job1 title', + description: 'This is job1 description', + createdAt: '2024-01-03T14:56:04.019Z', + updatedAt: '2024-01-03T14:56:04.019Z', + companyId: '5fbe70c2-16be-49d1-a529-79ff3a5b443f', + }, + { + id: '9be63e1e-d57d-4491-bcc9-3eda8e5f2061', + title: 'adsasdasd', + description: 'asdasdasdasd', + createdAt: '2024-01-15T18:30:12.441Z', + updatedAt: '2024-01-15T18:30:12.441Z', + companyId: 'a3329765-cd33-46e5-a929-43fdad43bd93', + }, + ], + hasPrevious: false, + hasNext: false, + totalPages: 1, + isLast: true, + isFirst: true, + }, + }, + }, + }) @Roles(Role.USER) @UseGuards(JwtAuthGuard, RoleGuard) @ApiBody({ type: Object }) @@ -156,4 +191,44 @@ export class UserController { console.info('#UserGetProfileInfoById request incoming'); return await this.userService.findOneById(params.id); } + + @ApiBearerAuth() + @ApiCookieAuth() + @ApiParam({ + name: 'contractId', + type: String, + description: 'contractId of the job vacancy that want to be deleted', + }) + @ApiResponse({ + schema: { + example: { + status: true, + statusCode: 200, + data: { + id: '19eb7629-3cc4-49ec-8a50-eba25f9d2a62', + userId: 'd557b674-7f45-4734-9115-2ef1154959bc', + jobId: '9a6402b9-9a20-4ab1-bb15-9324398cef39', + paymentId: null, + title: + 'Lowongan pekerjaan Enna Alouette for d557b674-7f45-4734-9115-2ef1154959bc', + description: 'Contract for the following job description: auauaaa', + paymentRate: null, + template: null, + createdAt: '2024-01-16T17:35:13.586Z', + updatedAt: '2024-01-16T17:35:13.586Z', + status: 'PENDING', + customField: null, + workSubmission: null, + ratingId: null, + }, + }, + }, + }) + @Roles(Role.USER) + @UseGuards(JwtAuthGuard, RoleGuard) + @Get('unapply/:contractId') + async unapplyJobByContractId(@Request() req, @Res() res) { + console.info('#unapplyJobByContractId request incoming'); + return await this.userService.unApplyJobByContractId(req.params.contractId); + } } diff --git a/src/users/user.repository.ts b/src/users/user.repository.ts index d74b725..28418ef 100644 --- a/src/users/user.repository.ts +++ b/src/users/user.repository.ts @@ -155,6 +155,7 @@ export class UserRepository { ...pagination(page, size), include: { jobVacancy: true, + payment: true, }, orderBy: { createdAt: 'asc', @@ -171,9 +172,14 @@ export class UserRepository { throw new HttpException({ prisma: e.message }, HttpStatus.BAD_REQUEST); } - console.log('#getAppliedJob res', res); - - const jobList = res?.contract.map((contract) => contract.jobVacancy); + const jobList = res?.contract.map((contract) => { + return { + ...contract.jobVacancy, + contractId: contract.id, + contractStatus: contract.status, + paymentStatus: contract.payment?.paymentStatus, + }; + }); const total = res?._count.contract; return returnablePaginated(jobList, total, page, size); } diff --git a/src/users/users.module.ts b/src/users/users.module.ts index 3863751..68c1f41 100644 --- a/src/users/users.module.ts +++ b/src/users/users.module.ts @@ -5,6 +5,7 @@ import { UserController } from './user.controller'; import { UserRepository } from './user.repository'; import { UserHelper } from './user.helper'; import { CompanyRepository } from '../company/company.repository'; +import { ContractRepository } from '../contract/contract.repository'; @Module({ providers: [ @@ -13,6 +14,7 @@ import { CompanyRepository } from '../company/company.repository'; UserRepository, UserHelper, CompanyRepository, + ContractRepository, ], exports: [UsersService], controllers: [UserController], diff --git a/src/users/users.service.ts b/src/users/users.service.ts index 245525c..ea210e7 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -4,12 +4,14 @@ import { UserFilterRequestDto } from './dto/user-filter.dto'; import { UserHelper } from './user.helper'; import { User } from '@prisma/client'; import { CompanyRepository } from '../company/company.repository'; +import { ContractRepository } from '../contract/contract.repository'; @Injectable() export class UsersService { constructor( private userRepository: UserRepository, private companyRepository: CompanyRepository, + private contractRepository: ContractRepository, private userHelper: UserHelper, ) {} @@ -110,4 +112,8 @@ export class UsersService { ): Promise { return this.userRepository.getAppliedJob(userId, page, size); } + + async unApplyJobByContractId(contractId: string) { + return this.contractRepository.delete(contractId); + } }