BREAKING CHANGE(bank_codes): shift-codes table and expenses-codes table deleted and refactoring of modules calling "x-codes" to use bank-codes

This commit is contained in:
Matthieu Haineault 2025-07-30 14:39:43 -04:00
parent f85a213561
commit f874d2c5c6
26 changed files with 205 additions and 539 deletions

View File

@ -0,0 +1,16 @@
/*
Warnings:
- You are about to drop the column `expense_code_id` on the `expenses_archive` table. All the data in the column will be lost.
- You are about to drop the column `shift_code_id` on the `shifts_archive` table. All the data in the column will be lost.
- Added the required column `bank_code_id` to the `expenses_archive` table without a default value. This is not possible if the table is not empty.
- Added the required column `bank_code_id` to the `shifts_archive` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "expenses_archive" DROP COLUMN "expense_code_id",
ADD COLUMN "bank_code_id" INTEGER NOT NULL;
-- AlterTable
ALTER TABLE "shifts_archive" DROP COLUMN "shift_code_id",
ADD COLUMN "bank_code_id" INTEGER NOT NULL;

View File

@ -132,7 +132,7 @@ model LeaveRequestsArchive {
//pay-period vue //pay-period vue
view PayPeriods { view PayPeriods {
period_number Int @id period_number Int @id //do not try to fix it, Prisma is working on a fix for views
start_date DateTime @db.Date start_date DateTime @db.Date
end_date DateTime @db.Date end_date DateTime @db.Date
year Int year Int
@ -169,7 +169,7 @@ model Shifts {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
timesheet Timesheets @relation("ShiftTimesheet", fields: [timesheet_id], references: [id]) timesheet Timesheets @relation("ShiftTimesheet", fields: [timesheet_id], references: [id])
timesheet_id Int timesheet_id Int
shift_code BankCodes @relation("ShiftBankCodes", fields: [bank_code_id], references: [id]) bank_code BankCodes @relation("ShiftBankCodes", fields: [bank_code_id], references: [id])
bank_code_id Int bank_code_id Int
description String? description String?
date DateTime @db.Date date DateTime @db.Date
@ -182,16 +182,16 @@ model Shifts {
} }
model ShiftsArchive { model ShiftsArchive {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
shift Shifts @relation("ShiftsToArchive", fields: [shift_id], references: [id]) shift Shifts @relation("ShiftsToArchive", fields: [shift_id], references: [id])
shift_id Int shift_id Int
archive_at DateTime @default(now()) archive_at DateTime @default(now())
timesheet_id Int timesheet_id Int
shift_code_id Int bank_code_id Int
description String? description String?
date DateTime @db.Date date DateTime @db.Date
start_time DateTime @db.Time(0) start_time DateTime @db.Time(0)
end_time DateTime @db.Time(0) end_time DateTime @db.Time(0)
@@map("shifts_archive") @@map("shifts_archive")
} }
@ -234,7 +234,7 @@ model ExpensesArchive {
expense_id Int expense_id Int
timesheet_id Int timesheet_id Int
archived_at DateTime @default(now()) archived_at DateTime @default(now())
expense_code_id Int bank_code_id Int
date DateTime @db.Date date DateTime @db.Date
amount Decimal @db.Money amount Decimal @db.Money
attachement String? attachement String?

View File

@ -0,0 +1,12 @@
import { Module } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { BankCodesControllers } from "./controllers/bank-codes.controller";
import { BankCodesService } from "./services/bank-codes.services";
@Module({
controllers: [BankCodesControllers],
providers: [BankCodesService, PrismaService],
})
export class ShiftCodesModule {}

View File

@ -0,0 +1,46 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
import { BankCodesService } from "../services/bank-codes.services";
import { CreateBankCodeDto } from "../dtos/create-bank-codes";
import { UpdateBankCodeDto } from "../dtos/update-bank-codes";
import { ApiBadRequestResponse, ApiNotFoundResponse, ApiOperation, ApiResponse } from "@nestjs/swagger";
@Controller('bank-codes')
export class BankCodesControllers {
constructor(private readonly bankCodesService: BankCodesService) {}
@Post()
@ApiOperation({ summary: 'Create a new bank code' })
@ApiResponse({ status: 201, description: 'Bank code successfully created.' })
@ApiBadRequestResponse({ description: 'Invalid input data.' })
create(@Body() dto: CreateBankCodeDto) {
return this.bankCodesService.create(dto);
}
@Get()
@ApiOperation({ summary: 'Retrieve all bank codes' })
@ApiResponse({ status: 200, description: 'List of bank codes.' })
findAll() {
return this.bankCodesService.findAll();
}
@Get(':id')
@ApiOperation({ summary: 'Retrieve a bank code by its ID' })
@ApiNotFoundResponse({ description: 'Bank code not found.' })
findOne(@Param('id', ParseIntPipe) id: number){
return this.bankCodesService.findOne(id);
}
@Patch(':id')
@ApiOperation({ summary: 'Update an existing bank code' })
@ApiNotFoundResponse({ description: 'Bank code not found.' })
update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateBankCodeDto) {
return this.bankCodesService.update(id, dto)
}
@Delete(':id')
@ApiOperation({ summary: 'Delete a bank code' })
@ApiNotFoundResponse({ description: 'Bank code not found.' })
remove(@Param('id', ParseIntPipe) id: number) {
return this.bankCodesService.remove(id);
}
}

View File

@ -0,0 +1,20 @@
import { IsNotEmpty, IsNumber, IsString } from "class-validator";
export class CreateBankCodeDto {
@IsString()
@IsNotEmpty()
type: string;
@IsString()
@IsNotEmpty()
categorie: string;
@IsNumber()
@IsNotEmpty()
modifier: number;
@IsString()
@IsNotEmpty()
bank_code: string;
}

View File

@ -0,0 +1,34 @@
import { ApiProperty } from "@nestjs/swagger";
export class BankCodesEntity {
@ApiProperty({
example: 1,
description: 'Unique ID of a bank-code (auto-generated)',
})
id: number;
@ApiProperty({
example: 'regular, vacation, emergency, sick, parental, etc',
description: 'Type of codes',
})
type: string;
@ApiProperty({
example: 'shift, expense, leave',
description: 'categorie of the related code',
})
categorie: string;
@ApiProperty({
example: '0, 0.72, 1, 1.5, 2',
description: 'modifier number to apply to salary',
})
modifier: number;
@ApiProperty({
example: 'G1, G345, G501, G43, G700',
description: 'codes given by the bank',
})
bank_code: string;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from "@nestjs/swagger";
import { CreateBankCodeDto } from "./create-bank-codes";
export class UpdateBankCodeDto extends PartialType(CreateBankCodeDto) {}

View File

@ -0,0 +1,38 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateBankCodeDto } from "../dtos/create-bank-codes";
import { BankCodes } from "@prisma/client";
import { UpdateBankCodeDto } from "../dtos/update-bank-codes";
@Injectable()
export class BankCodesService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateBankCodeDto): Promise<BankCodes>{
return this.prisma.bankCodes.create({ data: dto })
}
findAll() {
return this.prisma.bankCodes.findMany();
}
async findOne(id: number) {
const bankCode = await this.prisma.bankCodes.findUnique({ where: {id} });
if(!bankCode) {
throw new NotFoundException(`Bank Code #${id} not found`);
}
return bankCode;
}
async update(id:number, dto: UpdateBankCodeDto) {
await this.prisma.bankCodes.update({ where: { id }, data: dto });
}
async remove(id: number) {
await this.findOne(id);
return this.prisma.bankCodes.delete({ where: {id} });
}
}

View File

@ -1,64 +0,0 @@
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

@ -1,21 +0,0 @@
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

@ -1,21 +0,0 @@
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

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

View File

@ -1,11 +0,0 @@
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

@ -1,99 +0,0 @@
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

@ -1,61 +1,32 @@
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer"; import { Type } from "class-transformer";
import { IsBoolean, IsDate, IsDateString, IsInt, IsOptional, IsString } from "class-validator"; import { IsBoolean, IsDate, IsDateString, IsInt, IsOptional, IsString } from "class-validator";
export class CreateExpenseDto { export class CreateExpenseDto {
@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 an expense code (link with shift-codes)',
})
@Type(() => Number) @Type(() => Number)
@IsInt() @IsInt()
expense_code_id: number; bank_code_id: number;
@ApiProperty({
example: '20/10/3018',
description: 'Date where the expense was made',
})
@IsDateString() @IsDateString()
@Type(() => Date) @Type(() => Date)
@IsDate() @IsDate()
date: Date; date: Date;
@ApiProperty({
example: '280 000 000,00',
description: 'Amount of the expense',
})
@Type(() => Number) @Type(() => Number)
@IsInt() @IsInt()
amount: number amount: number
@ApiProperty({
example:'Spent for mileage between A and B',
description:'explain`s why the expense was made'
})
@IsString() @IsString()
description?: string; description?: string;
@ApiProperty({
example: 'True or False or Pending or Denied or Cancelled or Escalated',
description: 'Expense`s approval status',
})
@IsOptional() @IsOptional()
@IsBoolean() @IsBoolean()
is_approved?: boolean; 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() @IsString()
supervisor_comment?: string; supervisor_comment?: string;
} }

View File

@ -16,9 +16,9 @@ export class ExpenseEntity {
@ApiProperty({ @ApiProperty({
example: 7, example: 7,
description: 'ID number of an expense code (link with expense-codes)', description: 'ID number of an bank code (link with bank-codes)',
}) })
expense: number; bank_code_id: number;
@ApiProperty({ @ApiProperty({
example: '3018-10-20T00:00:00.000Z', example: '3018-10-20T00:00:00.000Z',

View File

@ -9,17 +9,17 @@ export class ExpensesService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateExpenseDto): Promise<Expenses> { async create(dto: CreateExpenseDto): Promise<Expenses> {
const { timesheet_id, expense_code_id, date, amount, const { timesheet_id, bank_code_id, date, amount,
description, is_approved,supervisor_comment} = dto; description, is_approved,supervisor_comment} = dto;
return this.prisma.expenses.create({ return this.prisma.expenses.create({
data: { timesheet_id, expense_code_id,date,amount,description,is_approved,supervisor_comment}, data: { timesheet_id, bank_code_id,date,amount,description,is_approved,supervisor_comment},
include: { include: {
timesheet: { timesheet: {
include: { include: {
employee: { include: { user: true } }, employee: { include: { user: true } },
}, },
}, },
expense_code: true, bank_code: true,
}, },
}); });
} }
@ -45,7 +45,7 @@ export class ExpensesService {
employee: { include: { user:true } }, employee: { include: { user:true } },
}, },
}, },
expense_code: true, bank_code: true,
}, },
}); });
if (!expense) { if (!expense) {
@ -56,13 +56,13 @@ export class ExpensesService {
async update(id: number, dto: UpdateExpenseDto): Promise<Expenses> { async update(id: number, dto: UpdateExpenseDto): Promise<Expenses> {
await this.findOne(id); await this.findOne(id);
const { timesheet_id, expense_code_id, date, amount, const { timesheet_id, bank_code_id, date, amount,
description, is_approved, supervisor_comment} = dto; description, is_approved, supervisor_comment} = dto;
return this.prisma.expenses.update({ return this.prisma.expenses.update({
where: { id }, where: { id },
data: { data: {
...(timesheet_id !== undefined && { timesheet_id}), ...(timesheet_id !== undefined && { timesheet_id}),
...(expense_code_id !== undefined && { expense_code_id }), ...(bank_code_id !== undefined && { bank_code_id }),
...(date !== undefined && { date }), ...(date !== undefined && { date }),
...(amount !== undefined && { amount }), ...(amount !== undefined && { amount }),
...(description !== undefined && { description }), ...(description !== undefined && { description }),
@ -77,7 +77,7 @@ export class ExpensesService {
}, },
}, },
}, },
expense_code: true, bank_code: true,
}, },
}); });
} }
@ -116,7 +116,7 @@ export class ExpensesService {
data: expensesToArchive.map(exp => ({ data: expensesToArchive.map(exp => ({
expense_id: exp.id, expense_id: exp.id,
timesheet_id: exp.timesheet_id, timesheet_id: exp.timesheet_id,
expense_code_id: exp.expense_code_id, bank_code_id: exp.bank_code_id,
date: exp.date, date: exp.date,
amount: exp.amount, amount: exp.amount,
attachement: exp.attachement, attachement: exp.attachement,

View File

@ -1,64 +0,0 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post, UseGuards } from "@nestjs/common";
import { ShiftCodesService } from "../services/shift-codes.service";
import { CreateShiftCodeDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
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";
import { JwtAuthGuard } from "src/modules/authentication/guards/jwt-auth.guard";
import { ShiftCodesEntity } from "../dtos/swagger-entities/shift-codes.entity";
@ApiTags('Shift Codes')
@ApiBearerAuth('access-token')
@UseGuards(JwtAuthGuard)
@Controller('shift-codes')
export class ShiftCodesController {
constructor(private readonly shiftCodesService: ShiftCodesService) {}
@Post()
@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: CreateShiftCodeDto): Promise<ShiftCodes> {
return this.shiftCodesService.create(dto);
}
@Get()
@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[]> {
return this.shiftCodesService.findAll();
}
@Get(':id')
@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> {
return this.shiftCodesService.findOne(id);
}
@Patch(':id')
@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,
@Body() dto: UpdateShiftCodeDto): Promise<ShiftCodes> {
return this.shiftCodesService.update(id,dto);
}
@Delete(':id')
@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> {
return this.shiftCodesService.remove(id);
}
}

View File

@ -1,21 +0,0 @@
import { ApiProperty } from "@nestjs/swagger";
import { IsNotEmpty, IsString } from "class-validator";
export class CreateShiftCodeDto {
@ApiProperty({
example: 'Regular or Night or Emergency, etc...',
description: 'Type of shifts for an account perception',
})
@IsString()
@IsNotEmpty()
shift_type: string;
@ApiProperty({
example: 'G1, G2, G3, etc...',
description: 'bank`s code related to the type of shift',
})
@IsString()
@IsNotEmpty()
bank_code: string;
}

View File

@ -1,21 +0,0 @@
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;
}

View File

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

View File

@ -1,109 +0,0 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateShiftCodeDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
import { UpdateShiftCodeDto } from "../dtos/update-shift-codes.dto";
@Injectable()
export class ShiftCodesService {
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateShiftCodeDto): Promise<ShiftCodes> {
const { shift_type, bank_code } = dto;
return this.prisma.shiftCodes.create({
data: { shift_type, bank_code },
include: {
shift: {
include: {
timesheet: {
include: {
employee: {
include: {
user: true,
},
},
},
},
},
},
},
});
}
findAll(): Promise<ShiftCodes[]> {
return this.prisma.shiftCodes.findMany({
include: {
shift: {
include: {
timesheet: {
include: {
employee: {
include: {
user: true
}
}
}
}
},
},
},
});
}
async findOne(id: number): Promise<ShiftCodes> {
const record = await this.prisma.shiftCodes.findUnique({
where: { id },
include: {
shift: {
include: {
timesheet: {
include: {
employee: {
include: {
user:true,
}
}
}
}
}
}
}
});
if(!record) {
throw new NotFoundException(`ShiftCode #${id} not found`);
}
return record;
}
async update(id: number, dto: UpdateShiftCodeDto): Promise<ShiftCodes> {
await this.findOne(id);
const { shift_type, bank_code } = dto;
return this.prisma.shiftCodes.update({
where: { id },
data: {
...(shift_type !== undefined && { shift_type }),
...(bank_code !== undefined && { bank_code }),
},
include: {
shift: {
include: {
timesheet: {
include: {
employee: {
include: {
user: true
}
}
}
},
},
},
},
});
}
async remove(id:number): Promise<ShiftCodes>{
await this.findOne(id);
return this.prisma.shiftCodes.delete({ where: { id }});
}
}

View File

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

View File

@ -1,56 +1,31 @@
import { ApiProperty } from "@nestjs/swagger";
import { Type } from "class-transformer"; import { Type } from "class-transformer";
import { IsDate, IsDateString, IsInt, IsString } from "class-validator"; import { IsDate, IsDateString, IsInt, IsString } 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; bank_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()
end_time: Date; end_time: Date;
@ApiProperty({
example:'Called for an emergency at X` place',
description:'justify the purpose of the shift'
})
@IsString() @IsString()
description: string; description: string;
} }

View File

@ -15,9 +15,9 @@ export class ShiftEntity {
@ApiProperty({ @ApiProperty({
example: 7, example: 7,
description: 'ID number of a shift code (link with shift-codes)', description: 'ID number of a shift code (link with bank-codes)',
}) })
shift_code_id: number; bank_code_id: number;
@ApiProperty({ @ApiProperty({
example: '3018-10-20T00:00:00.000Z', example: '3018-10-20T00:00:00.000Z',

View File

@ -9,16 +9,16 @@ export class ShiftsService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateShiftDto): Promise<Shifts> { async create(dto: CreateShiftDto): Promise<Shifts> {
const { timesheet_id, shift_code_id, date, start_time, end_time } = dto; const { timesheet_id, bank_code_id, date, start_time, end_time } = dto;
return this.prisma.shifts.create({ return this.prisma.shifts.create({
data: { timesheet_id, shift_code_id, date, start_time, end_time }, data: { timesheet_id, bank_code_id, date, start_time, end_time },
include: { include: {
timesheet: { timesheet: {
include: { include: {
employee: { include: { user: true } }, employee: { include: { user: true } },
}, },
}, },
shift_code: true, bank_code: true,
}, },
}); });
} }
@ -48,7 +48,7 @@ export class ShiftsService {
}, },
}, },
}, },
shift_code: true, bank_code: true,
}, },
}); });
if(!shift) { if(!shift) {
@ -59,12 +59,12 @@ export class ShiftsService {
async update(id: number, dto: UpdateShiftsDto): Promise<Shifts> { async update(id: number, dto: UpdateShiftsDto): Promise<Shifts> {
await this.findOne(id); await this.findOne(id);
const { timesheet_id, shift_code_id, date,start_time,end_time} = dto; const { timesheet_id, bank_code_id, date,start_time,end_time} = dto;
return this.prisma.shifts.update({ return this.prisma.shifts.update({
where: { id }, where: { id },
data: { data: {
...(timesheet_id !== undefined && { timesheet_id }), ...(timesheet_id !== undefined && { timesheet_id }),
...(shift_code_id !== undefined && { shift_code_id }), ...(bank_code_id !== undefined && { bank_code_id }),
...(date !== undefined && { date }), ...(date !== undefined && { date }),
...(start_time !== undefined && { start_time }), ...(start_time !== undefined && { start_time }),
...(end_time !== undefined && { end_time }), ...(end_time !== undefined && { end_time }),
@ -77,7 +77,7 @@ export class ShiftsService {
}, },
}, },
}, },
shift_code: true, bank_code: true,
}, },
}); });
} }
@ -115,7 +115,7 @@ export class ShiftsService {
data: shiftsToArchive.map(shift => ({ data: shiftsToArchive.map(shift => ({
shift_id: shift.id, shift_id: shift.id,
timesheet_id: shift.timesheet_id, timesheet_id: shift.timesheet_id,
shift_code_id: shift.shift_code_id, bank_code_id: shift.bank_code_id,
description: shift.description ?? undefined, description: shift.description ?? undefined,
date: shift.date, date: shift.date,
start_time: shift.start_time, start_time: shift.start_time,