feat(module): expense et expense_codes modules

This commit is contained in:
Matthieu Haineault 2025-07-24 09:55:29 -04:00
parent c8decf1026
commit 1ee7ec9052
20 changed files with 599 additions and 96 deletions

View File

@ -84,6 +84,7 @@ model Shifts {
timesheet_id Int
shift_code ShiftCodes @relation("ShiftShiftCode", fields: [shift_code_id], references: [id])
shift_code_id Int
description String?
date DateTime
start_time DateTime
end_time DateTime

View File

@ -0,0 +1,64 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
import { ExpenseCodesService } from "../services/expense-codes.service";
import { ApiTags, ApiBearerAuth, ApiOperation, ApiResponse } from "@nestjs/swagger";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { ExpenseCodes } from "@prisma/client";
import { Roles as RoleEnum } from '.prisma/client';
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { CreateExpenseCodeDto } from "../dtos/create-expense-code";
import { ExpenseCodesEntity } from "../dtos/swagger-entities/expense-codes.entity";
import { UpdateExpenseCodeDto } from "../dtos/update-expense-code";
@ApiTags('Expense Codes')
@ApiBearerAuth('access-token')
@UseGuards(JwtAuthGuard)
@Controller('expense-codes')
export class ExpenseCodesController {
constructor(private readonly expenseCodesService: ExpenseCodesService) {}
@Post()
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
@ApiOperation({ summary: 'Create expense code' })
@ApiResponse({ status: 201, description: 'Expense code created',type: ExpenseCodesEntity })
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
create(@Body()dto: CreateExpenseCodeDto): Promise<ExpenseCodes> {
return this.expenseCodesService.create(dto);
}
@Get()
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
@ApiOperation({ summary: 'Find all expense codes' })
@ApiResponse({ status: 201, description: 'List of expense codes found',type: ExpenseCodesEntity, isArray: true })
@ApiResponse({ status: 400, description: 'List of expense codes not found' })
findAll(): Promise<ExpenseCodes[]> {
return this.expenseCodesService.findAll();
}
@Get(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
@ApiOperation({ summary: 'Find expense code' })
@ApiResponse({ status: 201, description: 'Expense code found',type: ExpenseCodesEntity })
@ApiResponse({ status: 400, description: 'Expense code not found' })
findOne(@Param('id', ParseIntPipe) id: number): Promise<ExpenseCodes> {
return this.expenseCodesService.findOne(id);
}
@Patch(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
@ApiOperation({ summary: 'Update expense code' })
@ApiResponse({ status: 201, description: 'Expense code updated',type: ExpenseCodesEntity })
@ApiResponse({ status: 400, description: 'Expense code not found' })
update(@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateExpenseCodeDto): Promise<ExpenseCodes> {
return this.expenseCodesService.update(id,dto);
}
@Delete(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR)
@ApiOperation({ summary: 'Delete expense code' })
@ApiResponse({ status: 201, description: 'Expense code deleted',type: ExpenseCodesEntity })
@ApiResponse({ status: 400, description: 'Expense code not found' })
remove(@Param('id', ParseIntPipe)id: number): Promise<ExpenseCodes> {
return this.expenseCodesService.remove(id);
}
}

View File

@ -0,0 +1,21 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsString } from "class-validator";
export class CreateExpenseCodeDto {
@ApiProperty({
example:'mileage, overnight, etc...',
description: 'Type of expenses for an account perception',
})
@IsString()
@IsNotEmpty()
expense_type: string;
@ApiProperty({
example: 'G500, G501, etc...',
description: 'bank`s code related to the type of expense',
})
@IsString()
@IsNotEmpty()
bank_code: string;
}

View File

@ -0,0 +1,21 @@
import { ApiProperty } from "@nestjs/swagger";
export class ExpenseCodesEntity {
@ApiProperty({
example: 1,
description: 'Unique ID of a expense-code (auto-generated)',
})
id: number;
@ApiProperty({
example: 'Mileage',
description: 'Type of expenses for an account perception',
})
shift_type: string;
@ApiProperty({
example: 'G501',
description: 'bank`s code related to the type of expense',
})
bank_code: string;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from "@nestjs/swagger";
import { CreateExpenseCodeDto } from "./create-expense-code";
export class UpdateExpenseCodeDto extends PartialType(CreateExpenseCodeDto) {}

View File

@ -0,0 +1,11 @@
import { Module } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { ExpenseCodesController } from "./controllers/expense-codes.controller";
import { ExpenseCodesService } from "./services/expense-codes.service";
@Module({
controllers: [ExpenseCodesController],
providers: [ExpenseCodesService, PrismaService]
})
export class ExpenseCodesModule {}

View File

@ -0,0 +1,99 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateExpenseCodeDto } from "../dtos/create-expense-code";
import { ExpenseCodes } from "@prisma/client";
import { UpdateExpenseCodeDto } from "../dtos/update-expense-code";
@Injectable()
export class ExpenseCodesService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateExpenseCodeDto): Promise<ExpenseCodes> {
const { expense_type, bank_code } = dto;
return this.prisma.expenseCodes.create({
data: { expense_type, bank_code },
include: {
expense: {
include: {
timesheet: {
include: {
employee: { include: { user: true } },
},
},
},
},
},
});
}
findAll(): Promise<ExpenseCodes[]> {
return this.prisma.expenseCodes.findMany({
include: {
expense: {
include: {
timesheet: {
include: {
employee: {
include: { user: true }
},
},
},
},
},
},
});
}
async findOne(id: number): Promise<ExpenseCodes> {
const record = await this.prisma.expenseCodes.findUnique({
where: { id },
include: {
expense: {
include: {
timesheet: {
include: {
employee: {
include: { user:true },
},
},
},
},
},
},
});
if(!record) {
throw new NotFoundException(`ExpenseCode #${id} not found`);
}
return record;
}
async update(id: number, dto: UpdateExpenseCodeDto): Promise<ExpenseCodes> {
await this.findOne(id);
const { expense_type, bank_code } = dto;
return this.prisma.expenseCodes.update({
where: { id },
data: {
...(expense_type !== undefined && { expense_type }),
...(bank_code !== undefined && { bank_code }),
},
include: {
expense: {
include: {
timesheet: {
include: {
employee: {
include: { user: true },
},
},
},
},
},
},
});
}
async remove(id: number): Promise<ExpenseCodes> {
await this.findOne(id);
return this.prisma.expenseCodes.delete({ where: { id } });
}
}

View File

@ -0,0 +1,64 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
import { ExpensesService } from "../services/expenses.service";
import { CreateExpenseDto } from "../dtos/create-expense";
import { Expenses } from "@prisma/client";
import { Roles as RoleEnum } from '.prisma/client';
import { UpdateExpenseDto } from "../dtos/update-expense";
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { ExpenseEntity } from "../dtos/swagger-entities/expenses.entity";
@ApiTags('Expenses')
@ApiBearerAuth('access-token')
@UseGuards(JwtAuthGuard)
@Controller('Expenses')
export class ExpensesController {
constructor(private readonly expensesService: ExpensesService) {}
@Post()
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Create expense' })
@ApiResponse({ status: 201, description: 'Expense created',type: ExpenseEntity })
@ApiResponse({ status: 400, description: 'Incomplete task or invalid data' })
create(@Body() dto: CreateExpenseDto): Promise<Expenses> {
return this.expensesService.create(dto);
}
@Get()
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Find all expenses' })
@ApiResponse({ status: 201, description: 'List of expenses found',type: ExpenseEntity, isArray: true })
@ApiResponse({ status: 400, description: 'List of expenses not found' })
findAll(): Promise<Expenses[]> {
return this.expensesService.findAll();
}
@Get(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Find expense' })
@ApiResponse({ status: 201, description: 'Expense found',type: ExpenseEntity })
@ApiResponse({ status: 400, description: 'Expense not found' })
findOne(@Param('id', ParseIntPipe) id: number): Promise <Expenses> {
return this.expensesService.findOne(id);
}
@Patch(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Expense shift' })
@ApiResponse({ status: 201, description: 'Expense updated',type: ExpenseEntity })
@ApiResponse({ status: 400, description: 'Expense not found' })
update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateExpenseDto) {
return this.expensesService.update(id,dto);
}
@Delete(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Delete expense' })
@ApiResponse({ status: 201, description: 'Expense deleted',type: ExpenseEntity })
@ApiResponse({ status: 400, description: 'Expense not found' })
remove(@Param('id', ParseIntPipe) id: number): Promise<Expenses> {
return this.expensesService.remove(id);
}
}

View File

@ -0,0 +1,61 @@
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsBoolean, IsDate, IsDateString, IsInt, IsOptional, IsString } from "class-validator";
export class CreateExpenseDto {
@ApiProperty({
example: 'Th3F3110w5h1pX2024',
description: 'ID number for a set timesheet',
})
@Type(()=> Number)
@IsInt()
timesheet_id: number;
@ApiProperty({
example: '0n3R1n962Ru13xX',
description: 'ID number of an expense code (link with shift-codes)',
})
@Type(() => Number)
@IsInt()
expense_code_id: number;
@ApiProperty({
example: '20/10/3018',
description: 'Date where the expense was made',
})
@IsDateString()
@Type(() => Date)
@IsDate()
date: Date;
@ApiProperty({
example: '280 000 000,00',
description: 'Amount of the expense',
})
@Type(() => Number)
@IsInt()
amount: number
@ApiProperty({
example:'Spent for mileage between A and B',
description:'explain`s why the expense was made'
})
@IsString()
description?: string;
@ApiProperty({
example: 'True or False or Pending or Denied or Cancelled or Escalated',
description: 'Expense`s approval status',
})
@IsOptional()
@IsBoolean()
is_approved?: boolean;
@ApiProperty({
example:'Asked X to go there as an emergency response',
description:'Supervisro`s justification for the spending of an employee'
})
@IsString()
supervisor_comment?: string;
}

View File

@ -0,0 +1,46 @@
import { ApiProperty } from "@nestjs/swagger";
export class ExpenseEntity {
@ApiProperty({
example: 1,
description: 'Unique ID of the expense (auto-generated)',
})
id: number;
@ApiProperty({
example: 101,
description: 'ID number for a set timesheet',
})
timesheet_id: number;
@ApiProperty({
example: 7,
description: 'ID number of an expense code (link with expense-codes)',
})
expense: number;
@ApiProperty({
example: '3018-10-20T00:00:00.000Z',
description: 'Date where the expense was made',
})
date: Date;
@ApiProperty({
example: 'DENIED, APPROUVED, PENDING, etc...',
description: 'validation status',
})
is_approuved: boolean;
@ApiProperty({
example:'Spent for mileage between A and B',
description:'explain`s why the expense was made'
})
description: string;
@ApiProperty({
example:'Asked X to go there as an emergency response',
description:'Supervisro`s justification for the spending of an employee'
})
supervisor_comment: string;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from "@nestjs/swagger";
import { CreateExpenseDto } from "./create-expense";
export class UpdateExpenseDto extends PartialType(CreateExpenseDto) {}

View File

@ -0,0 +1,11 @@
import { PrismaService } from "src/prisma/prisma.service";
import { ExpensesController } from "./controllers/expenses.controller";
import { Module } from "@nestjs/common";
import { ExpensesService } from "./services/expenses.service";
@Module({
controllers: [ExpensesController],
providers: [ExpensesService, PrismaService]
})
export class ExpensesModule {}

View File

@ -0,0 +1,89 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateExpenseDto } from "../dtos/create-expense";
import { Expenses } from "@prisma/client";
import { UpdateExpenseDto } from "../dtos/update-expense";
@Injectable()
export class ExpensesService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateExpenseDto): Promise<Expenses> {
const { timesheet_id, expense_code_id, date, amount,
description, is_approved,supervisor_comment} = dto;
return this.prisma.expenses.create({
data: { timesheet_id, expense_code_id,date,amount,description,is_approved,supervisor_comment},
include: {
timesheet: {
include: {
employee: { include: { user: true } },
},
},
expense_code: true,
},
});
}
findAll(): Promise<Expenses[]> {
return this.prisma.expenses.findMany({
include: {
timesheet: {
include: {
employee: { include: { user: true } },
},
},
},
});
}
async findOne(id: number): Promise<Expenses> {
const expense = await this.prisma.expenses.findUnique({
where: { id },
include: {
timesheet: {
include: {
employee: { include: { user:true } },
},
},
expense_code: true,
},
});
if (!expense) {
throw new NotFoundException(`Expense #${id} not found`);
}
return expense;
}
async update(id: number, dto: UpdateExpenseDto): Promise<Expenses> {
await this.findOne(id);
const { timesheet_id, expense_code_id, date, amount,
description, is_approved, supervisor_comment} = dto;
return this.prisma.expenses.update({
where: { id },
data: {
...(timesheet_id !== undefined && { timesheet_id}),
...(expense_code_id !== undefined && { expense_code_id }),
...(date !== undefined && { date }),
...(amount !== undefined && { amount }),
...(description !== undefined && { description }),
...(is_approved !== undefined && { is_approved }),
...(supervisor_comment !== undefined && { supervisor_comment }),
},
include: {
timesheet: {
include: {
employee: {
include: { user: true }
},
},
},
expense_code: true,
},
});
}
async remove(id: number): Promise<Expenses> {
await this.findOne(id);
return this.prisma.expenses.delete({ where: { id } });
}
}

View File

@ -1,8 +1,8 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
import { ShiftCodesService } from "../services/shift-codes.service";
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
import { CreateShiftCodeDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
import { UpdateShiftCodeDto } from "../dtos/update-shift-codes.dto";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { Roles as RoleEnum } from '.prisma/client';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
@ -21,7 +21,7 @@ export class ShiftCodesController {
@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: CreateShiftCodeDto): Promise<ShiftCodes> {
return this.shiftCodesService.create(dto);
}
@ -49,7 +49,7 @@ export class ShiftCodesController {
@ApiResponse({ status: 201, description: 'Shift code updated',type: ShiftCodesEntity })
@ApiResponse({ status: 400, description: 'Shift code not found' })
update(@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateShiftCodesDto): Promise<ShiftCodes> {
@Body() dto: UpdateShiftCodeDto): Promise<ShiftCodes> {
return this.shiftCodesService.update(id,dto);
}

View File

@ -1,7 +1,7 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsString } from "class-validator";
export class CreateShiftCodesDto {
export class CreateShiftCodeDto {
@ApiProperty({
example: 'Regular or Night or Emergency, etc...',

View File

@ -1,4 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateShiftCodesDto } from './create-shift-codes.dto';
import { CreateShiftCodeDto } from './create-shift-codes.dto';
export class UpdateShiftCodesDto extends PartialType(CreateShiftCodesDto) {}
export class UpdateShiftCodeDto extends PartialType(CreateShiftCodeDto) {}

View File

@ -1,14 +1,14 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
import { CreateShiftCodeDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
import { UpdateShiftCodeDto } from "../dtos/update-shift-codes.dto";
@Injectable()
export class ShiftCodesService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateShiftCodesDto): Promise<ShiftCodes> {
async create(dto: CreateShiftCodeDto): Promise<ShiftCodes> {
const { shift_type, bank_code } = dto;
return this.prisma.shiftCodes.create({
data: { shift_type, bank_code },
@ -75,7 +75,7 @@ export class ShiftCodesService {
return record;
}
async update(id: number, dto: UpdateShiftCodesDto): Promise<ShiftCodes> {
async update(id: number, dto: UpdateShiftCodeDto): Promise<ShiftCodes> {
await this.findOne(id);
const { shift_type, bank_code } = dto;
return this.prisma.shiftCodes.update({

View File

@ -8,4 +8,4 @@ import { PrismaService } from "src/prisma/prisma.service";
providers: [ShiftCodesService, PrismaService],
})
export class ShiftCodeModule {}
export class ShiftCodesModule {}

View File

@ -16,49 +16,49 @@ import { ShiftEntity } from "../dtos/swagger-entities/shift.entity";
export class ShiftsController {
constructor(private readonly shiftsService: ShiftsService){}
@Post()
@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> {
return this.shiftsService.create(dto);
}
@Get()
@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[]> {
return this.shiftsService.findAll();
}
@Get(':id')
@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> {
return this.shiftsService.findOne(id);
}
@Patch(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Update shift' })
@ApiResponse({ status: 201, description: 'Shift updated',type: ShiftEntity })
@ApiResponse({ status: 400, description: 'Shift not found' })
update(@Param('id', ParseIntPipe) id: number,@Body() dto: UpdateShiftsDto): Promise<Shifts> {
return this.shiftsService.update(id, dto);
}
@Delete(':id')
@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> {
return this.shiftsService.remove(id);
}
@Post()
@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> {
return this.shiftsService.create(dto);
}
@Get()
@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[]> {
return this.shiftsService.findAll();
}
@Get(':id')
@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> {
return this.shiftsService.findOne(id);
}
@Patch(':id')
@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR)
@ApiOperation({ summary: 'Update shift' })
@ApiResponse({ status: 201, description: 'Shift updated',type: ShiftEntity })
@ApiResponse({ status: 400, description: 'Shift not found' })
update(@Param('id', ParseIntPipe) id: number,@Body() dto: UpdateShiftsDto): Promise<Shifts> {
return this.shiftsService.update(id, dto);
}
@Delete(':id')
@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> {
return this.shiftsService.remove(id);
}
}

View File

@ -1,49 +1,56 @@
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { IsDate, IsDateString, IsInt } from "class-validator";
import { IsDate, IsDateString, IsInt, IsString } from "class-validator";
export class CreateShiftDto {
@ApiProperty({
example: 'Th3F3110w5h1pX2024',
description: 'ID number for a set timesheet',
})
@Type(() => Number)
@IsInt()
timesheet_id: number;
@ApiProperty({
example: 'Th3F3110w5h1pX2024',
description: 'ID number for a set timesheet',
})
@Type(() => Number)
@IsInt()
timesheet_id: number;
@ApiProperty({
example: '0n3R1n962Ru13xX',
description: 'ID number of a shift code (link with shift-codes)',
})
@Type(() => Number)
@IsInt()
shift_code_id: number;
@ApiProperty({
example: '0n3R1n962Ru13xX',
description: 'ID number of a shift code (link with shift-codes)',
})
@Type(() => Number)
@IsInt()
shift_code_id: number;
@ApiProperty({
example: '20/10/3018',
description: 'Date where the shift takes place',
})
@IsDateString()
@Type(() => Date)
@IsDate()
date: Date;
@ApiProperty({
example: '20/10/3018',
description: 'Date where the shift takes place',
})
@IsDateString()
@Type(() => Date)
@IsDate()
date: Date;
@ApiProperty({
example: '08:00',
description: 'Start time of the said shift',
})
@IsDateString()
@Type(() => Date)
@IsDate()
start_time: Date;
@ApiProperty({
example: '08:00',
description: 'Start time of the said shift',
})
@IsDateString()
@Type(() => Date)
@IsDate()
start_time: Date;
@ApiProperty({
example: '17:00',
description: 'End time of the said shift',
})
@IsDateString()
@Type(() => Date)
@IsDate()
end_time: Date;
}
@ApiProperty({
example: '17:00',
description: 'End time of the said shift',
})
@IsDateString()
@Type(() => Date)
@IsDate()
end_time: Date;
@ApiProperty({
example:'Called for an emergency at X` place',
description:'justify the purpose of the shift'
})
@IsString()
description: string;
}