diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a7bb477..43c2cda 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -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 diff --git a/src/modules/expense-codes/controllers/expense-codes.controller.ts b/src/modules/expense-codes/controllers/expense-codes.controller.ts new file mode 100644 index 0000000..e120ca8 --- /dev/null +++ b/src/modules/expense-codes/controllers/expense-codes.controller.ts @@ -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 { + 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 { + 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 { + 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 { + 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 { + return this.expenseCodesService.remove(id); + } +} \ No newline at end of file diff --git a/src/modules/expense-codes/dtos/create-expense-code.ts b/src/modules/expense-codes/dtos/create-expense-code.ts new file mode 100644 index 0000000..7e8bf90 --- /dev/null +++ b/src/modules/expense-codes/dtos/create-expense-code.ts @@ -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; +} \ No newline at end of file diff --git a/src/modules/expense-codes/dtos/swagger-entities/expense-codes.entity.ts b/src/modules/expense-codes/dtos/swagger-entities/expense-codes.entity.ts new file mode 100644 index 0000000..08a5aec --- /dev/null +++ b/src/modules/expense-codes/dtos/swagger-entities/expense-codes.entity.ts @@ -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; +} \ No newline at end of file diff --git a/src/modules/expense-codes/dtos/update-expense-code.ts b/src/modules/expense-codes/dtos/update-expense-code.ts new file mode 100644 index 0000000..f2413e3 --- /dev/null +++ b/src/modules/expense-codes/dtos/update-expense-code.ts @@ -0,0 +1,4 @@ +import { PartialType } from "@nestjs/swagger"; +import { CreateExpenseCodeDto } from "./create-expense-code"; + +export class UpdateExpenseCodeDto extends PartialType(CreateExpenseCodeDto) {} \ No newline at end of file diff --git a/src/modules/expense-codes/expense-codes.module.ts b/src/modules/expense-codes/expense-codes.module.ts new file mode 100644 index 0000000..92e5d77 --- /dev/null +++ b/src/modules/expense-codes/expense-codes.module.ts @@ -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 {} \ No newline at end of file diff --git a/src/modules/expense-codes/services/expense-codes.service.ts b/src/modules/expense-codes/services/expense-codes.service.ts new file mode 100644 index 0000000..4428aaa --- /dev/null +++ b/src/modules/expense-codes/services/expense-codes.service.ts @@ -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 { + 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 { + return this.prisma.expenseCodes.findMany({ + include: { + expense: { + include: { + timesheet: { + include: { + employee: { + include: { user: true } + }, + }, + }, + }, + }, + }, + }); + } + + async findOne(id: number): Promise { + 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 { + 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 { + await this.findOne(id); + return this.prisma.expenseCodes.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/src/modules/expenses/controllers/expenses.controller.ts b/src/modules/expenses/controllers/expenses.controller.ts new file mode 100644 index 0000000..91e5b93 --- /dev/null +++ b/src/modules/expenses/controllers/expenses.controller.ts @@ -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 { + 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 { + 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 { + 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 { + return this.expensesService.remove(id); + } + +} \ No newline at end of file diff --git a/src/modules/expenses/dtos/create-expense.ts b/src/modules/expenses/dtos/create-expense.ts new file mode 100644 index 0000000..b2037b8 --- /dev/null +++ b/src/modules/expenses/dtos/create-expense.ts @@ -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; +} diff --git a/src/modules/expenses/dtos/swagger-entities/expenses.entity.ts b/src/modules/expenses/dtos/swagger-entities/expenses.entity.ts new file mode 100644 index 0000000..2fbdbcd --- /dev/null +++ b/src/modules/expenses/dtos/swagger-entities/expenses.entity.ts @@ -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; +} \ No newline at end of file diff --git a/src/modules/expenses/dtos/update-expense.ts b/src/modules/expenses/dtos/update-expense.ts new file mode 100644 index 0000000..dda40eb --- /dev/null +++ b/src/modules/expenses/dtos/update-expense.ts @@ -0,0 +1,4 @@ +import { PartialType } from "@nestjs/swagger"; +import { CreateExpenseDto } from "./create-expense"; + +export class UpdateExpenseDto extends PartialType(CreateExpenseDto) {} \ No newline at end of file diff --git a/src/modules/expenses/expenses.module.ts b/src/modules/expenses/expenses.module.ts new file mode 100644 index 0000000..3432561 --- /dev/null +++ b/src/modules/expenses/expenses.module.ts @@ -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 {} \ No newline at end of file diff --git a/src/modules/expenses/services/expenses.service.ts b/src/modules/expenses/services/expenses.service.ts new file mode 100644 index 0000000..e92be77 --- /dev/null +++ b/src/modules/expenses/services/expenses.service.ts @@ -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 { + 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 { + return this.prisma.expenses.findMany({ + include: { + timesheet: { + include: { + employee: { include: { user: true } }, + }, + }, + }, + }); + } + + async findOne(id: number): Promise { + 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 { + 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 { + await this.findOne(id); + return this.prisma.expenses.delete({ where: { id } }); + } +} \ No newline at end of file diff --git a/src/modules/shift-codes/controllers/shift-codes.controller.ts b/src/modules/shift-codes/controllers/shift-codes.controller.ts index db16eb6..0b34a68 100644 --- a/src/modules/shift-codes/controllers/shift-codes.controller.ts +++ b/src/modules/shift-codes/controllers/shift-codes.controller.ts @@ -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 { + create(@Body()dto: CreateShiftCodeDto): Promise { 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 { + @Body() dto: UpdateShiftCodeDto): Promise { return this.shiftCodesService.update(id,dto); } diff --git a/src/modules/shift-codes/dtos/create-shift-codes.dto.ts b/src/modules/shift-codes/dtos/create-shift-codes.dto.ts index 3fa173c..5cdff72 100644 --- a/src/modules/shift-codes/dtos/create-shift-codes.dto.ts +++ b/src/modules/shift-codes/dtos/create-shift-codes.dto.ts @@ -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...', diff --git a/src/modules/shift-codes/dtos/update-shift-codes.dto.ts b/src/modules/shift-codes/dtos/update-shift-codes.dto.ts index 93f5c3f..bb956c6 100644 --- a/src/modules/shift-codes/dtos/update-shift-codes.dto.ts +++ b/src/modules/shift-codes/dtos/update-shift-codes.dto.ts @@ -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) {} diff --git a/src/modules/shift-codes/services/shift-codes.service.ts b/src/modules/shift-codes/services/shift-codes.service.ts index 2912350..c88b958 100644 --- a/src/modules/shift-codes/services/shift-codes.service.ts +++ b/src/modules/shift-codes/services/shift-codes.service.ts @@ -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 { + async create(dto: CreateShiftCodeDto): Promise { 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 { + async update(id: number, dto: UpdateShiftCodeDto): Promise { await this.findOne(id); const { shift_type, bank_code } = dto; return this.prisma.shiftCodes.update({ diff --git a/src/modules/shift-codes/shift-codes.module.ts b/src/modules/shift-codes/shift-codes.module.ts index 8bc2594..a8574ae 100644 --- a/src/modules/shift-codes/shift-codes.module.ts +++ b/src/modules/shift-codes/shift-codes.module.ts @@ -8,4 +8,4 @@ import { PrismaService } from "src/prisma/prisma.service"; providers: [ShiftCodesService, PrismaService], }) -export class ShiftCodeModule {} \ No newline at end of file +export class ShiftCodesModule {} \ No newline at end of file diff --git a/src/modules/shifts/controllers/shifts.controller.ts b/src/modules/shifts/controllers/shifts.controller.ts index d1d23b0..c7ed0ca 100644 --- a/src/modules/shifts/controllers/shifts.controller.ts +++ b/src/modules/shifts/controllers/shifts.controller.ts @@ -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 { - 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 { - 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 { - 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 { - 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 { - 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 { + 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 { + 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 { + 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 { + 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 { + return this.shiftsService.remove(id); + } } \ No newline at end of file diff --git a/src/modules/shifts/dtos/create-shifts.dto.ts b/src/modules/shifts/dtos/create-shifts.dto.ts index 2ed7dcb..f17403d 100644 --- a/src/modules/shifts/dtos/create-shifts.dto.ts +++ b/src/modules/shifts/dtos/create-shifts.dto.ts @@ -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; -} \ No newline at end of file + @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; +}