Merge branch 'main' of git.targo.ca:Targo/targo_backend into origin/dev/setup/AuthMiddleware/NicolasD
This commit is contained in:
commit
615f0848e5
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -56,3 +56,5 @@ pids
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
/generated/prisma
|
/generated/prisma
|
||||||
|
|
||||||
|
!swagger-spec.json
|
||||||
|
|
|
||||||
2285
docs/swagger/swagger-spec.json
Normal file
2285
docs/swagger/swagger-spec.json
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -12,6 +12,7 @@ import { LeaveRequestsModule } from './modules/leave-requests/leave-requests.mod
|
||||||
import { ShiftCodeModule } from './modules/shift-codes/shift-codes.module';
|
import { ShiftCodeModule } from './modules/shift-codes/shift-codes.module';
|
||||||
import { ShiftsModule } from './modules/shifts/shifts.module';
|
import { ShiftsModule } from './modules/shifts/shifts.module';
|
||||||
import { TimesheetsModule } from './modules/timesheets/timesheets.module';
|
import { TimesheetsModule } from './modules/timesheets/timesheets.module';
|
||||||
|
import { AuthenticationModule } from './modules/authentication/auth.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|
@ -25,6 +26,7 @@ import { TimesheetsModule } from './modules/timesheets/timesheets.module';
|
||||||
ShiftCodeModule,
|
ShiftCodeModule,
|
||||||
ShiftsModule,
|
ShiftsModule,
|
||||||
TimesheetsModule,
|
TimesheetsModule,
|
||||||
|
AuthenticationModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController, HealthController],
|
controllers: [AppController, HealthController],
|
||||||
providers: [AppService],
|
providers: [AppService],
|
||||||
|
|
|
||||||
37
src/main.ts
37
src/main.ts
|
|
@ -5,11 +5,13 @@ import { ValidationPipe } from '@nestjs/common';
|
||||||
import { JwtAuthGuard } from './modules/authentication/guards/jwt-auth.guard';
|
import { JwtAuthGuard } from './modules/authentication/guards/jwt-auth.guard';
|
||||||
import { RolesGuard } from './common/guards/roles.guard';
|
import { RolesGuard } from './common/guards/roles.guard';
|
||||||
import { OwnershipGuard } from './common/guards/ownership.guard';
|
import { OwnershipGuard } from './common/guards/ownership.guard';
|
||||||
|
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
||||||
|
import { writeFileSync } from 'fs';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
//setup Reflector for Roles()
|
|
||||||
const reflector = app.get(Reflector);
|
const reflector = app.get(Reflector); //setup Reflector for Roles()
|
||||||
|
|
||||||
app.useGlobalPipes(
|
app.useGlobalPipes(
|
||||||
new ValidationPipe({ whitelist: true, transform: true}));
|
new ValidationPipe({ whitelist: true, transform: true}));
|
||||||
|
|
@ -19,6 +21,37 @@ async function bootstrap() {
|
||||||
new OwnershipGuard(reflector, app.get(ModuleRef)), //Global use of OwnershipGuard, not implemented yet
|
new OwnershipGuard(reflector, app.get(ModuleRef)), //Global use of OwnershipGuard, not implemented yet
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//swagger config
|
||||||
|
const config = new DocumentBuilder()
|
||||||
|
.setTitle('Targo_Backend')
|
||||||
|
.setDescription('Documentation de l`API REST pour Targo (NestJS + Prisma)')
|
||||||
|
.setVersion('1.0')
|
||||||
|
.addBearerAuth({
|
||||||
|
type: 'http',
|
||||||
|
scheme: 'bearer',
|
||||||
|
bearerFormat: 'JWT',
|
||||||
|
name: 'Authorization',
|
||||||
|
description: 'Invalid JWT token',
|
||||||
|
in: 'header',
|
||||||
|
}, 'access-token')
|
||||||
|
.addTag('Users')
|
||||||
|
.addTag('Employees')
|
||||||
|
.addTag('Customers')
|
||||||
|
.addTag('Timesheets')
|
||||||
|
.addTag('Shifts')
|
||||||
|
.addTag('Leave Requests')
|
||||||
|
.addTag('Shift Codes')
|
||||||
|
.addTag('OAuth Access Tokens')
|
||||||
|
.addTag('Authorization')
|
||||||
|
.build();
|
||||||
|
|
||||||
|
//document builder for swagger docs
|
||||||
|
const documentFactory = () => SwaggerModule.createDocument(app, config);
|
||||||
|
const document = documentFactory()
|
||||||
|
SwaggerModule.setup('api/docs', app, document);
|
||||||
|
|
||||||
|
writeFileSync('./docs/swagger/swagger-spec.json', JSON.stringify(document, null, 2));
|
||||||
|
|
||||||
await app.listen(process.env.PORT ?? 3000);
|
await app.listen(process.env.PORT ?? 3000);
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|
|
||||||
|
|
@ -1,35 +1,53 @@
|
||||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from '@nestjs/common';
|
||||||
import { CustomersService } from '../services/customers.service';
|
import { CustomersService } from '../services/customers.service';
|
||||||
import { Customers, Employees } from '@prisma/client';
|
import { Customers } from '@prisma/client';
|
||||||
import { CreateCustomerDto } from '../dtos/create-customer';
|
import { CreateCustomerDto } from '../dtos/create-customer.dto';
|
||||||
import { UpdateCustomerDto } from '../dtos/update-customer';
|
import { UpdateCustomerDto } from '../dtos/update-customer.dto';
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard';
|
||||||
|
import { CustomerEntity } from '../dtos/swagger-entities/customers.entity';
|
||||||
|
|
||||||
|
@ApiTags('Customers')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('customers')
|
@Controller('customers')
|
||||||
export class CustomersController {
|
export class CustomersController {
|
||||||
constructor(private readonly customersService: CustomersService) {}
|
constructor(private readonly customersService: CustomersService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Create customer' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Customer created', type: CustomerEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Invalid task or invalid data' })
|
||||||
create(@Body() dto: CreateCustomerDto): Promise<Customers> {
|
create(@Body() dto: CreateCustomerDto): Promise<Customers> {
|
||||||
return this.customersService.create(dto);
|
return this.customersService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find all customers' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of customers found', type: CustomerEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of customers not found' })
|
||||||
findAll(): Promise<Customers[]> {
|
findAll(): Promise<Customers[]> {
|
||||||
return this.customersService.findAll();
|
return this.customersService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find customer' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Customer found', type: CustomerEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Customer not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<Customers> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<Customers> {
|
||||||
return this.customersService.findOne(id);
|
return this.customersService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE,RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE,RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Update customer' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Customer updated', type: CustomerEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Customer not found' })
|
||||||
update(
|
update(
|
||||||
@Param('id', ParseIntPipe) id: number,
|
@Param('id', ParseIntPipe) id: number,
|
||||||
@Body() dto: UpdateCustomerDto,
|
@Body() dto: UpdateCustomerDto,
|
||||||
|
|
@ -39,6 +57,9 @@ export class CustomersController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Delete customer' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Customer deleted', type: CustomerEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Customer not found' })
|
||||||
remove(@Param('id', ParseIntPipe) id: number): Promise<Customers>{
|
remove(@Param('id', ParseIntPipe) id: number): Promise<Customers>{
|
||||||
return this.customersService.remove(id);
|
return this.customersService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
64
src/modules/customers/dtos/create-customer.dto.ts
Normal file
64
src/modules/customers/dtos/create-customer.dto.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
import {
|
||||||
|
IsEmail,
|
||||||
|
IsInt,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsOptional,
|
||||||
|
IsPositive,
|
||||||
|
IsString,
|
||||||
|
} from "class-validator";
|
||||||
|
|
||||||
|
export class CreateCustomerDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Gandalf',
|
||||||
|
description: 'Customer`s first name',
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
first_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'TheGray',
|
||||||
|
description: 'Customer`s last name',
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
last_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'you_shall_not_pass@middleEarth.com',
|
||||||
|
description: 'Customer`s email',
|
||||||
|
})
|
||||||
|
@IsEmail()
|
||||||
|
@IsOptional()
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '8436637464',
|
||||||
|
description: 'Customer`s phone number',
|
||||||
|
})
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsInt()
|
||||||
|
@IsPositive()
|
||||||
|
phone_number: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '1 Ringbearer`s way, Mount Doom city, ME, T1R 1N6 ',
|
||||||
|
description: 'Customer`s residence',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
residence?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '4263253',
|
||||||
|
description: 'Customer`s invoice number',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
@IsInt()
|
||||||
|
@IsNotEmpty()
|
||||||
|
invoice_id: number;
|
||||||
|
}
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
import { Type } from "class-transformer";
|
|
||||||
import {
|
|
||||||
IsEmail,
|
|
||||||
IsInt,
|
|
||||||
IsNotEmpty,
|
|
||||||
IsOptional,
|
|
||||||
IsPositive,
|
|
||||||
IsString,
|
|
||||||
} from "class-validator";
|
|
||||||
|
|
||||||
export class CreateCustomerDto {
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
first_name: string;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsNotEmpty()
|
|
||||||
last_name: string;
|
|
||||||
|
|
||||||
@IsEmail()
|
|
||||||
@IsOptional()
|
|
||||||
email?: string;
|
|
||||||
|
|
||||||
@Type(() => Number)
|
|
||||||
@IsInt()
|
|
||||||
@IsPositive()
|
|
||||||
phone_number: number;
|
|
||||||
|
|
||||||
@IsString()
|
|
||||||
@IsOptional()
|
|
||||||
residence?: string;
|
|
||||||
|
|
||||||
@IsInt()
|
|
||||||
@IsNotEmpty()
|
|
||||||
invoice_id: number;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class CustomerEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Unique ID of a customer(primary-key, auto-incremented)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '0e6e2e1f-b157-4c7c-ae3f-999b3e4f914d',
|
||||||
|
description: 'UUID of the user linked to that customer',
|
||||||
|
})
|
||||||
|
user_id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'you_shall_not_pass@middleEarth.com',
|
||||||
|
description: 'customer`s email (optional)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
email?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 8436637464,
|
||||||
|
description: 'customer`s phone number (numbers only)',
|
||||||
|
})
|
||||||
|
phone_number: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '1 Ringbearer’s way, Mount Doom city, ME, T1R 1N6',
|
||||||
|
description: 'customer`s residence address (optional)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
residence?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 4263253,
|
||||||
|
description: 'customer`s invoice number (optionnal, unique)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
invoice_id?: number;
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { PartialType } from "@nestjs/swagger";
|
import { PartialType } from "@nestjs/swagger";
|
||||||
import { CreateCustomerDto } from "./create-customer";
|
import { CreateCustomerDto } from "./create-customer.dto";
|
||||||
|
|
||||||
export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {}
|
export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||||
import { PrismaService } from 'src/prisma/prisma.service';
|
import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
import { CreateCustomerDto } from '../dtos/create-customer';
|
import { CreateCustomerDto } from '../dtos/create-customer.dto';
|
||||||
import { Customers, Users } from '@prisma/client';
|
import { Customers, Users } from '@prisma/client';
|
||||||
import { UpdateCustomerDto } from '../dtos/update-customer';
|
import { UpdateCustomerDto } from '../dtos/update-customer.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CustomersService {
|
export class CustomersService {
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,52 @@
|
||||||
import {
|
import { Body,Controller,Delete,Get,Param,ParseIntPipe,Patch,Post,UseGuards } from '@nestjs/common';
|
||||||
Body,
|
import { Employees, Roles as RoleEnum } from '@prisma/client';
|
||||||
Controller,
|
|
||||||
Delete,
|
|
||||||
Get,
|
|
||||||
Param,
|
|
||||||
ParseIntPipe,
|
|
||||||
Patch,
|
|
||||||
Post,
|
|
||||||
} from '@nestjs/common';
|
|
||||||
import { Employees } from '@prisma/client';
|
|
||||||
import { EmployeesService } from '../services/employees.service';
|
import { EmployeesService } from '../services/employees.service';
|
||||||
import { CreateEmployeeDto } from '../dtos/create-employee.dto';
|
import { CreateEmployeeDto } from '../dtos/create-employee.dto';
|
||||||
import { UpdateEmployeeDto } from '../dtos/update-employee.dto';
|
import { UpdateEmployeeDto } from '../dtos/update-employee.dto';
|
||||||
|
|
||||||
//decorators and roles imports
|
|
||||||
import { RolesAllowed } from '../../../common/decorators/roles.decorators';
|
import { RolesAllowed } from '../../../common/decorators/roles.decorators';
|
||||||
import { Roles as RoleEnum } from 'prisma/prisma-client';
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard';
|
||||||
|
import { EmployeeEntity } from '../dtos/swagger-entities/employees.entity';
|
||||||
|
|
||||||
|
@ApiTags('Employees')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('employees')
|
@Controller('employees')
|
||||||
export class EmployeesController {
|
export class EmployeesController {
|
||||||
constructor(private readonly employeesService: EmployeesService) {}
|
constructor(private readonly employeesService: EmployeesService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({summary: 'Create employee' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Employee created', type: EmployeeEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body() dto: CreateEmployeeDto): Promise<Employees> {
|
create(@Body() dto: CreateEmployeeDto): Promise<Employees> {
|
||||||
return this.employeesService.create(dto);
|
return this.employeesService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING)
|
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR, RoleEnum.ACCOUNTING)
|
||||||
|
@ApiOperation({summary: 'Find all employees' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of employees found', type: EmployeeEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of employees not found' })
|
||||||
findAll(): Promise<Employees[]> {
|
findAll(): Promise<Employees[]> {
|
||||||
return this.employeesService.findAll();
|
return this.employeesService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING )
|
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING )
|
||||||
|
@ApiOperation({summary: 'Find employee' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Employee found', type: EmployeeEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Employee not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
|
||||||
return this.employeesService.findOne(id);
|
return this.employeesService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING )
|
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR,RoleEnum.ACCOUNTING )
|
||||||
|
@ApiOperation({summary: 'Update employee' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Employee updated', type: EmployeeEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Employee not found' })
|
||||||
update(
|
update(
|
||||||
@Param('id', ParseIntPipe) id: number,
|
@Param('id', ParseIntPipe) id: number,
|
||||||
@Body() dto: UpdateEmployeeDto,
|
@Body() dto: UpdateEmployeeDto,
|
||||||
|
|
@ -50,6 +56,9 @@ export class EmployeesController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR )
|
@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR )
|
||||||
|
@ApiOperation({summary: 'Delete employee' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Employee deleted', type: EmployeeEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Employee not found' })
|
||||||
remove(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
|
remove(@Param('id', ParseIntPipe) id: number): Promise<Employees> {
|
||||||
return this.employeesService.remove(id);
|
return this.employeesService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,44 +9,84 @@ import {
|
||||||
IsString,
|
IsString,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { Type } from 'class-transformer';
|
import { Type } from 'class-transformer';
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
export class CreateEmployeeDto {
|
export class CreateEmployeeDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Frodo',
|
||||||
|
description: 'Employee`s first name',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
first_name: string;
|
first_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Baggins',
|
||||||
|
description: 'Employee`s last name',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
last_name: string;
|
last_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'i_cant_do_this_sam@targointernet.com',
|
||||||
|
description: 'Employee`s email',
|
||||||
|
})
|
||||||
@IsEmail()
|
@IsEmail()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
email: string;
|
email: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '82538437464',
|
||||||
|
description: 'Employee`s phone number',
|
||||||
|
})
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
phone_number: number;
|
phone_number: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '1 Bagshot Row, Hobbiton, The Shire, Middle-earth',
|
||||||
|
description: 'Employee`s residence',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
residence?: string;
|
residence?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'BagginsF7464',
|
||||||
|
description: 'Employee`s payroll id',
|
||||||
|
})
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
external_payroll_id: number;
|
external_payroll_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '335567447',
|
||||||
|
description: 'Employee`s company code',
|
||||||
|
})
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@IsPositive()
|
@IsPositive()
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
company_code: number;
|
company_code: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '23/09/3018',
|
||||||
|
description: 'Employee`s first working day',
|
||||||
|
})
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
first_work_day: Date;
|
first_work_day: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '25/03/3019',
|
||||||
|
description: 'Employee`s last working day',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class EmployeeEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Unique ID of an employee(primary-key, auto-incremented)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '0e6e2e1f-b157-4c7c-ae3f-999b3e4f914d',
|
||||||
|
description: 'UUID of the user linked to that employee',
|
||||||
|
})
|
||||||
|
user_id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 7464,
|
||||||
|
description: 'external ID for the pay system',
|
||||||
|
})
|
||||||
|
external_payroll_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 335567447,
|
||||||
|
description: 'company code',
|
||||||
|
})
|
||||||
|
company_code: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3018-09-23T00:00:00.000Z',
|
||||||
|
description: 'Employee first day at work',
|
||||||
|
})
|
||||||
|
first_work_day: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3019-03-25T00:00:00.000Z',
|
||||||
|
description: 'Employee last day at work',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
last_work_day?: Date;
|
||||||
|
}
|
||||||
|
|
@ -1,44 +1,62 @@
|
||||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
|
||||||
import { LeaveRequestsService } from "../services/leave-request.service";
|
import { LeaveRequestsService } from "../services/leave-request.service";
|
||||||
import { CreateLeaveRequestsDto } from "../dtos/create-leave-requests.dto";
|
import { CreateLeaveRequestsDto } from "../dtos/create-leave-requests.dto";
|
||||||
import { LeaveRequests } from "@prisma/client";
|
import { LeaveRequests } from "@prisma/client";
|
||||||
import { UpdateLeaveRequestsDto } from "../dtos/update-leave-requests.dto";
|
import { UpdateLeaveRequestsDto } from "../dtos/update-leave-requests.dto";
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||||
|
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
|
||||||
|
import { LeaveRequestEntity } from "../dtos/swagger-entities/leave-requests.entity";
|
||||||
|
|
||||||
|
@ApiTags('Leave Requests')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('leave-requests')
|
@Controller('leave-requests')
|
||||||
export class LeaveRequestController {
|
export class LeaveRequestController {
|
||||||
constructor(private readonly leaveRequetsService: LeaveRequestsService){}
|
constructor(private readonly leaveRequetsService: LeaveRequestsService){}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({summary: 'Create leave request' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Leave request created',type: LeaveRequestEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body() dto: CreateLeaveRequestsDto): Promise<LeaveRequests> {
|
create(@Body() dto: CreateLeaveRequestsDto): Promise<LeaveRequests> {
|
||||||
return this. leaveRequetsService.create(dto);
|
return this. leaveRequetsService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({summary: 'Find all leave request' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of Leave requests found',type: LeaveRequestEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'Leave request not found' })
|
||||||
findAll(): Promise<LeaveRequests[]> {
|
findAll(): Promise<LeaveRequests[]> {
|
||||||
return this.leaveRequetsService.findAll();
|
return this.leaveRequetsService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({summary: 'Find leave request' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Leave request found',type: LeaveRequestEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Leave request not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<LeaveRequests> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<LeaveRequests> {
|
||||||
return this.leaveRequetsService.findOne(id);
|
return this.leaveRequetsService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
update(
|
@ApiOperation({summary: 'Update leave request' })
|
||||||
@Param('id', ParseIntPipe) id: number,
|
@ApiResponse({ status: 201, description: 'Leave request updated',type: LeaveRequestEntity })
|
||||||
@Body() dto: UpdateLeaveRequestsDto,
|
@ApiResponse({ status: 400, description: 'Leave request not found' })
|
||||||
): Promise<LeaveRequests> {
|
update(@Param('id', ParseIntPipe) id: number,@Body() dto: UpdateLeaveRequestsDto): Promise<LeaveRequests> {
|
||||||
return this.leaveRequetsService.update(id, dto);
|
return this.leaveRequetsService.update(id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({summary: 'Delete leave request' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Leave request deleted',type: LeaveRequestEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Leave request not found' })
|
||||||
remove(@Param('id', ParseIntPipe) id: number): Promise<LeaveRequests> {
|
remove(@Param('id', ParseIntPipe) id: number): Promise<LeaveRequests> {
|
||||||
return this.leaveRequetsService.remove(id);
|
return this.leaveRequetsService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,52 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
|
import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsString } from "class-validator";
|
import { IsEnum, IsInt, IsNotEmpty, IsOptional, IsString } from "class-validator";
|
||||||
|
|
||||||
export class CreateLeaveRequestsDto {
|
export class CreateLeaveRequestsDto {
|
||||||
|
@ApiProperty({
|
||||||
|
example: '4655867',
|
||||||
|
description: 'Employee`s id',
|
||||||
|
})
|
||||||
@Type(()=> Number)
|
@Type(()=> Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
employee_id: number;
|
employee_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Sick or Vacation or Unpaid or Bereavement or Parental or Legal',
|
||||||
|
description: 'type of leave request for an accounting perception',
|
||||||
|
})
|
||||||
@IsEnum(LeaveTypes)
|
@IsEnum(LeaveTypes)
|
||||||
leave_type: LeaveTypes;
|
leave_type: LeaveTypes;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '22/06/2463',
|
||||||
|
description: 'Leave request`s start date',
|
||||||
|
})
|
||||||
@Type(()=>Date)
|
@Type(()=>Date)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
start_date_time:Date;
|
start_date_time:Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '25/03/3019',
|
||||||
|
description: 'Leave request`s end date',
|
||||||
|
})
|
||||||
@Type(()=>Date)
|
@Type(()=>Date)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
end_date_time?: Date;
|
end_date_time?: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'My precious',
|
||||||
|
description: 'Leave request`s comment',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
comment: string;
|
comment: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'True or False or Pending or Denied or Cancelled or Escalated',
|
||||||
|
description: 'Leave request`s approval status',
|
||||||
|
})
|
||||||
@IsEnum(LeaveApprovalStatus)
|
@IsEnum(LeaveApprovalStatus)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
approval_status?: LeaveApprovalStatus;
|
approval_status?: LeaveApprovalStatus;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { LeaveApprovalStatus, LeaveTypes } from '@prisma/client';
|
||||||
|
|
||||||
|
export class LeaveRequestEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Leave request`s unique id(auto-incremented)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 42,
|
||||||
|
description: 'ID of concerned employee',
|
||||||
|
})
|
||||||
|
employee_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'SICK',
|
||||||
|
enum: LeaveTypes,
|
||||||
|
description: 'type of leave request for an accounting perception',
|
||||||
|
})
|
||||||
|
leave_type: LeaveTypes;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '22/06/2463',
|
||||||
|
description: 'Leave request`s start date',
|
||||||
|
})
|
||||||
|
start_date_time: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '25/03/3019',
|
||||||
|
description: 'Leave request`s end date (optionnal)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
end_date_time?: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'My precious',
|
||||||
|
description: 'Leave request employee`s comment',
|
||||||
|
})
|
||||||
|
comment: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'PENDING',
|
||||||
|
enum: LeaveApprovalStatus,
|
||||||
|
description: 'Leave request`s approval status',
|
||||||
|
})
|
||||||
|
approval_status: LeaveApprovalStatus;
|
||||||
|
}
|
||||||
|
|
@ -1,41 +1,62 @@
|
||||||
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, Patch, Post, UseGuards } from '@nestjs/common';
|
||||||
import { OauthAccessTokensService } from '../services/oauth-access-tokens.service';
|
import { OauthAccessTokensService } from '../services/oauth-access-tokens.service';
|
||||||
import { CreateOauthAccessTokenDto } from '../dtos/create-oauth-access-token.dto';
|
import { CreateOauthAccessTokenDto } from '../dtos/create-oauth-access-token.dto';
|
||||||
import { OAuthAccessTokens } from '@prisma/client';
|
import { OAuthAccessTokens } from '@prisma/client';
|
||||||
import { UpdateOauthAccessTokenDto } from '../dtos/update-oauth-access-token.dto';
|
import { UpdateOauthAccessTokenDto } from '../dtos/update-oauth-access-token.dto';
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard';
|
||||||
|
import { OAuthAccessTokenEntity } from '../dtos/swagger-entities/oauth-access-token.entity';
|
||||||
|
|
||||||
|
@ApiTags('OAuth Access Tokens')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('oauth-access-tokens')
|
@Controller('oauth-access-tokens')
|
||||||
export class OauthAccessTokensController {
|
export class OauthAccessTokensController {
|
||||||
constructor(private readonly oauthAccessTokensService: OauthAccessTokensService){}
|
constructor(private readonly oauthAccessTokensService: OauthAccessTokensService){}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ADMIN)
|
@RolesAllowed(RoleEnum.ADMIN)
|
||||||
|
@ApiOperation({summary: 'Create OAuth access token' })
|
||||||
|
@ApiResponse({ status: 201, description: 'OAuth access token created', type: OAuthAccessTokenEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body()dto: CreateOauthAccessTokenDto): Promise<OAuthAccessTokens> {
|
create(@Body()dto: CreateOauthAccessTokenDto): Promise<OAuthAccessTokens> {
|
||||||
return this.oauthAccessTokensService.create(dto);
|
return this.oauthAccessTokensService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ADMIN)
|
@RolesAllowed(RoleEnum.ADMIN)
|
||||||
|
@ApiOperation({summary: 'Find all OAuth access token' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of OAuth access token found', type: OAuthAccessTokenEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of OAuth access token not found' })
|
||||||
findAll(): Promise<OAuthAccessTokens[]> {
|
findAll(): Promise<OAuthAccessTokens[]> {
|
||||||
return this.oauthAccessTokensService.findAll();
|
return this.oauthAccessTokensService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN)
|
@RolesAllowed(RoleEnum.ADMIN)
|
||||||
|
@ApiOperation({summary: 'Find OAuth access token' })
|
||||||
|
@ApiResponse({ status: 201, description: 'OAuth access token found', type: OAuthAccessTokenEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'OAuth access token not found' })
|
||||||
findOne(@Param('id') id: string): Promise<OAuthAccessTokens> {
|
findOne(@Param('id') id: string): Promise<OAuthAccessTokens> {
|
||||||
return this.oauthAccessTokensService.findOne(id);
|
return this.oauthAccessTokensService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN)
|
@RolesAllowed(RoleEnum.ADMIN)
|
||||||
|
@ApiOperation({summary: 'Update OAuth access token' })
|
||||||
|
@ApiResponse({ status: 201, description: 'OAuth access token updated', type: OAuthAccessTokenEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'OAuth access token not found' })
|
||||||
update(@Param('id') id: string, @Body() dto: UpdateOauthAccessTokenDto): Promise<OAuthAccessTokens> {
|
update(@Param('id') id: string, @Body() dto: UpdateOauthAccessTokenDto): Promise<OAuthAccessTokens> {
|
||||||
return this.oauthAccessTokensService.update(id,dto);
|
return this.oauthAccessTokensService.update(id,dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ADMIN)
|
@RolesAllowed(RoleEnum.ADMIN)
|
||||||
|
@ApiOperation({summary: 'Delete OAuth access token' })
|
||||||
|
@ApiResponse({ status: 201, description: 'OAuth access token deleted', type: OAuthAccessTokenEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'OAuth access token not found' })
|
||||||
remove(@Param('id') id: string): Promise<OAuthAccessTokens> {
|
remove(@Param('id') id: string): Promise<OAuthAccessTokens> {
|
||||||
return this.oauthAccessTokensService.remove(id);
|
return this.oauthAccessTokensService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,60 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
import { IsArray, IsDate, IsOptional, IsString, IsUUID } from "class-validator";
|
import { IsArray, IsDate, IsOptional, IsString, IsUUID } from "class-validator";
|
||||||
|
|
||||||
export class CreateOauthAccessTokenDto {
|
export class CreateOauthAccessTokenDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'S7A2U8R7O6N6',
|
||||||
|
description: 'User`s unique identification number',
|
||||||
|
})
|
||||||
@IsUUID()
|
@IsUUID()
|
||||||
user_id: string;
|
user_id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'app.targo.ca',
|
||||||
|
description: 'URL in which the access token is used for',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
application: string;
|
application: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'L5O6R4D3/O6F3#T8H4E3&R6I4N6G4S7 ...',
|
||||||
|
description: 'Access token',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
access_token: string;
|
access_token: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Th3731102h1p07Th3R1n92',
|
||||||
|
description: 'Refresh token',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
refresh_token: string;
|
refresh_token: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '25/12/3018',
|
||||||
|
description: 'Access token`s expiry date',
|
||||||
|
})
|
||||||
@Type(()=> Date)
|
@Type(()=> Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
access_token_expiry: Date;
|
access_token_expiry: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '26/02/3019',
|
||||||
|
description: 'Refresh token`s expiry date',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
@Type(()=> Date)
|
@Type(()=> Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
refresh_token_expiry?: Date;
|
refresh_token_expiry?: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'access tolkiens, email, etc... ',
|
||||||
|
description: 'scopes of infos linked to the access token',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
@IsArray()
|
@IsArray()
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class OAuthAccessTokenEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'cklwi0vb70000z2z20q6f19qk',
|
||||||
|
description: 'Unique ID of an OAuth token (auto-generated)',
|
||||||
|
})
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '0e6e2e1f-b157-4c7c-ae3f-999b3e4f914d',
|
||||||
|
description: 'UUID User`s unique identification number',
|
||||||
|
})
|
||||||
|
user_id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'app.targo.ca',
|
||||||
|
description: 'URL in which the access token is used for',
|
||||||
|
})
|
||||||
|
application: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'L5O6R4D3/O6F3#T8H4E3&R6I4N6G4S7',
|
||||||
|
description: 'Access token',
|
||||||
|
})
|
||||||
|
access_token: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Th3731102h1p07Th3R1n92',
|
||||||
|
description: 'Refresh token',
|
||||||
|
})
|
||||||
|
refresh_token: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3018-12-25T00:00:00.000Z',
|
||||||
|
description: 'Access token`s expiry date',
|
||||||
|
})
|
||||||
|
access_token_expiry: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3019-02-26T00:00:00.000Z',
|
||||||
|
description: 'Refresh token`s expiry date (optional)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
refresh_token_expiry?: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: ['email', 'profile', 'access_tolkiens'],
|
||||||
|
description: 'scopes of infos linked to the access token',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
scopes: string[];
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: false,
|
||||||
|
description: 'revoke status',
|
||||||
|
})
|
||||||
|
is_revoked: boolean;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '2025-07-22',
|
||||||
|
description: 'creation date',
|
||||||
|
})
|
||||||
|
created_at: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '2025-07-23',
|
||||||
|
description: 'Latest update (optional)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
updated_at?: Date;
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,53 @@
|
||||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
|
||||||
import { ShiftCodesService } from "../services/shift-codes.service";
|
import { ShiftCodesService } from "../services/shift-codes.service";
|
||||||
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
|
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
|
||||||
import { ShiftCodes } from "@prisma/client";
|
import { ShiftCodes } from "@prisma/client";
|
||||||
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
|
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||||
|
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
|
||||||
|
import { ShiftCodesEntity } from "../dtos/swagger-entities/shift-codes.entity";
|
||||||
|
|
||||||
@Controller()
|
@ApiTags('Shift Codes')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@Controller('shift-codes')
|
||||||
export class ShiftCodesController {
|
export class ShiftCodesController {
|
||||||
constructor(private readonly shiftCodesService: ShiftCodesService) {}
|
constructor(private readonly shiftCodesService: ShiftCodesService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
||||||
|
@ApiOperation({ summary: 'Create shift code' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift code created',type: ShiftCodesEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body()dto: CreateShiftCodesDto): Promise<ShiftCodes> {
|
create(@Body()dto: CreateShiftCodesDto): Promise<ShiftCodes> {
|
||||||
return this.shiftCodesService.create(dto);
|
return this.shiftCodesService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
||||||
|
@ApiOperation({ summary: 'Find all shift codes' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of shift codes found',type: ShiftCodesEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of shift codes not found' })
|
||||||
findAll(): Promise<ShiftCodes[]> {
|
findAll(): Promise<ShiftCodes[]> {
|
||||||
return this.shiftCodesService.findAll();
|
return this.shiftCodesService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
||||||
|
@ApiOperation({ summary: 'Find shift code' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift code found',type: ShiftCodesEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Shift code not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<ShiftCodes> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<ShiftCodes> {
|
||||||
return this.shiftCodesService.findOne(id);
|
return this.shiftCodesService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
||||||
|
@ApiOperation({ summary: 'Update shift code' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift code updated',type: ShiftCodesEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Shift code not found' })
|
||||||
update(@Param('id', ParseIntPipe) id: number,
|
update(@Param('id', ParseIntPipe) id: number,
|
||||||
@Body() dto: UpdateShiftCodesDto): Promise<ShiftCodes> {
|
@Body() dto: UpdateShiftCodesDto): Promise<ShiftCodes> {
|
||||||
return this.shiftCodesService.update(id,dto);
|
return this.shiftCodesService.update(id,dto);
|
||||||
|
|
@ -37,6 +55,9 @@ export class ShiftCodesController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
|
||||||
|
@ApiOperation({ summary: 'Delete shift code' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift code deleted',type: ShiftCodesEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Shift code not found' })
|
||||||
remove(@Param('id', ParseIntPipe)id: number): Promise<ShiftCodes> {
|
remove(@Param('id', ParseIntPipe)id: number): Promise<ShiftCodes> {
|
||||||
return this.shiftCodesService.remove(id);
|
return this.shiftCodesService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,20 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { IsNotEmpty, IsString } from "class-validator";
|
import { IsNotEmpty, IsString } from "class-validator";
|
||||||
|
|
||||||
export class CreateShiftCodesDto {
|
export class CreateShiftCodesDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Regular or Night or Emergency, etc...',
|
||||||
|
description: 'Type of shifts for an account perception',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
shift_type: string;
|
shift_type: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'G1, G2, G3, etc...',
|
||||||
|
description: 'bank`s code related to the type of shift',
|
||||||
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
bank_code: string;
|
bank_code: string;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class ShiftCodesEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Unique ID of a shift-code (auto-generated)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Night',
|
||||||
|
description: 'Type of shifts for an account perception',
|
||||||
|
})
|
||||||
|
shift_type: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'G2',
|
||||||
|
description: 'bank`s code related to the type of shift',
|
||||||
|
})
|
||||||
|
bank_code: string;
|
||||||
|
}
|
||||||
|
|
@ -1,45 +1,62 @@
|
||||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
|
||||||
import { ShiftsService } from "../services/shifts.service";
|
import { ShiftsService } from "../services/shifts.service";
|
||||||
import { Shifts } from "@prisma/client";
|
import { Shifts } from "@prisma/client";
|
||||||
import { CreateShiftDto } from "../dtos/create-shifts.dto";
|
import { CreateShiftDto } from "../dtos/create-shifts.dto";
|
||||||
import { UpdateShiftsDto } from "../dtos/update-shifts.dto";
|
import { UpdateShiftsDto } from "../dtos/update-shifts.dto";
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||||
|
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
|
||||||
|
import { ShiftEntity } from "../dtos/swagger-entities/shift.entity";
|
||||||
|
|
||||||
|
@ApiTags('Shifts')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('shifts')
|
@Controller('shifts')
|
||||||
export class ShiftsController {
|
export class ShiftsController {
|
||||||
constructor(private readonly shiftsService: ShiftsService){}
|
constructor(private readonly shiftsService: ShiftsService){}
|
||||||
|
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Create shift' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift created',type: ShiftEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body() dto: CreateShiftDto): Promise<Shifts> {
|
create(@Body() dto: CreateShiftDto): Promise<Shifts> {
|
||||||
return this.shiftsService.create(dto);
|
return this.shiftsService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find all shifts' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of shifts found',type: ShiftEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of shifts not found' })
|
||||||
findAll(): Promise<Shifts[]> {
|
findAll(): Promise<Shifts[]> {
|
||||||
return this.shiftsService.findAll();
|
return this.shiftsService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find shift' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift found',type: ShiftEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Shift not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
|
||||||
return this.shiftsService.findOne(id);
|
return this.shiftsService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
update(
|
@ApiOperation({ summary: 'Update shift' })
|
||||||
@Param('id', ParseIntPipe) id: number,
|
@ApiResponse({ status: 201, description: 'Shift updated',type: ShiftEntity })
|
||||||
@Body() dto: UpdateShiftsDto,
|
@ApiResponse({ status: 400, description: 'Shift not found' })
|
||||||
): Promise<Shifts> {
|
update(@Param('id', ParseIntPipe) id: number,@Body() dto: UpdateShiftsDto): Promise<Shifts> {
|
||||||
return this.shiftsService.update(id, dto);
|
return this.shiftsService.update(id, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Delete shift' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Shift deleted',type: ShiftEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Shift not found' })
|
||||||
remove(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
|
remove(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
|
||||||
return this.shiftsService.remove(id);
|
return this.shiftsService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,47 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
import { IsDate, IsDateString, IsInt } from "class-validator";
|
import { IsDate, IsDateString, IsInt } from "class-validator";
|
||||||
|
|
||||||
export class CreateShiftDto {
|
export class CreateShiftDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Th3F3110w5h1pX2024',
|
||||||
|
description: 'ID number for a set timesheet',
|
||||||
|
})
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
timesheet_id: number;
|
timesheet_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '0n3R1n962Ru13xX',
|
||||||
|
description: 'ID number of a shift code (link with shift-codes)',
|
||||||
|
})
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
shift_code_id: number;
|
shift_code_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '20/10/3018',
|
||||||
|
description: 'Date where the shift takes place',
|
||||||
|
})
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
date: Date;
|
date: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '08:00',
|
||||||
|
description: 'Start time of the said shift',
|
||||||
|
})
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
start_time: Date;
|
start_time: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '17:00',
|
||||||
|
description: 'End time of the said shift',
|
||||||
|
})
|
||||||
@IsDateString()
|
@IsDateString()
|
||||||
@Type(() => Date)
|
@Type(() => Date)
|
||||||
@IsDate()
|
@IsDate()
|
||||||
|
|
|
||||||
39
src/modules/shifts/dtos/swagger-entities/shift.entity.ts
Normal file
39
src/modules/shifts/dtos/swagger-entities/shift.entity.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class ShiftEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'Unique ID of the shift (auto-generated)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 101,
|
||||||
|
description: 'ID number for a set timesheet',
|
||||||
|
})
|
||||||
|
timesheet_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 7,
|
||||||
|
description: 'ID number of a shift code (link with shift-codes)',
|
||||||
|
})
|
||||||
|
shift_code_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3018-10-20T00:00:00.000Z',
|
||||||
|
description: 'Date where the shift takes place',
|
||||||
|
})
|
||||||
|
date: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3018-10-20T08:00:00.000Z',
|
||||||
|
description: 'Start time of the said shift',
|
||||||
|
})
|
||||||
|
start_time: Date;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '3018-10-20T17:00:00.000Z',
|
||||||
|
description: 'End time of the said shift',
|
||||||
|
})
|
||||||
|
end_time: Date;
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,53 @@
|
||||||
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
|
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from '@nestjs/common';
|
||||||
import { TimesheetsService } from '../services/timesheets.service';
|
import { TimesheetsService } from '../services/timesheets.service';
|
||||||
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
|
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
|
||||||
import { Timesheets } from '@prisma/client';
|
import { Timesheets } from '@prisma/client';
|
||||||
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
|
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
|
||||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||||
import { Roles as RoleEnum } from '.prisma/client';
|
import { Roles as RoleEnum } from '.prisma/client';
|
||||||
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
|
||||||
|
import { JwtAuthGuard } from 'src/modules/authentication/guards/jwt-auth.guard';
|
||||||
|
import { TimesheetEntity } from '../dtos/swagger-entities/timesheet.entity';
|
||||||
|
|
||||||
|
@ApiTags('Timesheets')
|
||||||
|
@ApiBearerAuth('access-token')
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
@Controller('timesheets')
|
@Controller('timesheets')
|
||||||
export class TimesheetsController {
|
export class TimesheetsController {
|
||||||
constructor(private readonly timesheetsService: TimesheetsService) {}
|
constructor(private readonly timesheetsService: TimesheetsService) {}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Create timesheet' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Timesheet created', type: TimesheetEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
|
||||||
create(@Body() dto: CreateTimesheetDto): Promise<Timesheets> {
|
create(@Body() dto: CreateTimesheetDto): Promise<Timesheets> {
|
||||||
return this.timesheetsService.create(dto);
|
return this.timesheetsService.create(dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find all timesheets' })
|
||||||
|
@ApiResponse({ status: 201, description: 'List of timesheet found', type: TimesheetEntity, isArray: true })
|
||||||
|
@ApiResponse({ status: 400, description: 'List of timesheets not found' })
|
||||||
findAll(): Promise<Timesheets[]> {
|
findAll(): Promise<Timesheets[]> {
|
||||||
return this.timesheetsService.findAll();
|
return this.timesheetsService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Find timesheet' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Timesheet found', type: TimesheetEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Timesheet not found' })
|
||||||
findOne(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
|
findOne(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
|
||||||
return this.timesheetsService.findOne(id);
|
return this.timesheetsService.findOne(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Update timesheet' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Timesheet updated', type: TimesheetEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Timesheet not found' })
|
||||||
update(
|
update(
|
||||||
@Param('id', ParseIntPipe) id:number,
|
@Param('id', ParseIntPipe) id:number,
|
||||||
@Body() dto: UpdateTimesheetDto,
|
@Body() dto: UpdateTimesheetDto,
|
||||||
|
|
@ -39,6 +57,9 @@ export class TimesheetsController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||||
|
@ApiOperation({ summary: 'Delete timesheet' })
|
||||||
|
@ApiResponse({ status: 201, description: 'Timesheet deleted', type: TimesheetEntity })
|
||||||
|
@ApiResponse({ status: 400, description: 'Timesheet not found' })
|
||||||
remove(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
|
remove(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
|
||||||
return this.timesheetsService.remove(id);
|
return this.timesheetsService.remove(id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { Type } from "class-transformer";
|
import { Type } from "class-transformer";
|
||||||
import { IsBoolean, IsInt, IsOptional } from "class-validator";
|
import { IsBoolean, IsInt, IsOptional } from "class-validator";
|
||||||
|
|
||||||
export class CreateTimesheetDto {
|
export class CreateTimesheetDto {
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: '426433',
|
||||||
|
description: 'employee`s ID number of linked timsheet',
|
||||||
|
})
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
employee_id: number;
|
employee_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'True or False or Pending or Denied or Cancelled or Escalated',
|
||||||
|
description: 'Timesheet`s approval status',
|
||||||
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
is_approved?: boolean;
|
is_approved?: boolean;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class TimesheetEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 1,
|
||||||
|
description: 'timesheet`s unique ID (auto-generated)',
|
||||||
|
})
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 426433,
|
||||||
|
description: 'employee`s ID number of linked timsheet',
|
||||||
|
})
|
||||||
|
employee_id: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: true,
|
||||||
|
description: 'Timesheet`s approval status',
|
||||||
|
})
|
||||||
|
is_approved: boolean;
|
||||||
|
}
|
||||||
48
src/modules/users-management/swagger-entities/user.entity.ts
Normal file
48
src/modules/users-management/swagger-entities/user.entity.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { ApiProperty } from '@nestjs/swagger';
|
||||||
|
import { Roles } from '@prisma/client';
|
||||||
|
|
||||||
|
export class UserEntity {
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'd67f05be-6dd1-464f-b5f7-31b325e21b4a',
|
||||||
|
description: 'User`s unique UUID (primary key)',
|
||||||
|
})
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Aragorn',
|
||||||
|
description: 'user`s first name',
|
||||||
|
})
|
||||||
|
first_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Elessar',
|
||||||
|
description: 'user`s last name',
|
||||||
|
})
|
||||||
|
last_name: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'king@arnor-gondor.gov',
|
||||||
|
description: 'Unique email address',
|
||||||
|
})
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 5141234567,
|
||||||
|
description: 'Unique phone number',
|
||||||
|
})
|
||||||
|
phone_number: number;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'Minas Tirith, Gondor',
|
||||||
|
description: 'residence address (optional)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
residence?: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
example: 'EMPLOYEE',
|
||||||
|
enum: Roles,
|
||||||
|
description: 'User`s given role',
|
||||||
|
})
|
||||||
|
role: Roles;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user