From fcf9635d53c378470ebc2b34f58bead718aaaab3 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Thu, 17 Jul 2025 09:48:42 -0400 Subject: [PATCH] feat(modules): CRUD for all modules --- prisma/schema.prisma | 3 +- .../controllers/customers.controller.ts | 38 ++++++++ src/modules/customers/customers.module.ts | 10 ++ .../customers/dtos/create-customers.ts | 37 +++++++ .../customers/dtos/update-customers.ts | 4 + .../customers/services/customers.service.ts | 97 +++++++++++++++++++ .../employees/dtos/create-employee.dto.ts | 13 +-- .../employees/services/employees.service.ts | 53 +++++++--- .../dtos/create-leave-requests.dto.ts | 3 + .../dtos/update-leave-requests.dto.ts | 3 + .../dtos/create-shift-codes.dto.ts | 11 +++ .../dtos/update-shift-codes.dto.ts | 4 + .../services/shift-codes.service.ts | 17 ++++ .../shifts/controllers/shifts.controller.ts | 6 ++ src/modules/shifts/dtos/create-shifts.dto.ts | 19 ++++ src/modules/shifts/dtos/update-shifts.dto.ts | 4 + src/modules/shifts/services/shifts.service.ts | 14 +++ src/modules/shifts/shifts.module.ts | 9 ++ 18 files changed, 316 insertions(+), 29 deletions(-) create mode 100644 src/modules/customers/controllers/customers.controller.ts create mode 100644 src/modules/customers/customers.module.ts create mode 100644 src/modules/customers/dtos/create-customers.ts create mode 100644 src/modules/customers/dtos/update-customers.ts create mode 100644 src/modules/customers/services/customers.service.ts create mode 100644 src/modules/shift-codes/dtos/create-shift-codes.dto.ts create mode 100644 src/modules/shift-codes/dtos/update-shift-codes.dto.ts diff --git a/prisma/schema.prisma b/prisma/schema.prisma index fea1ff5..d40e803 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -17,8 +17,7 @@ model Users { id String @id @default(uuid()) first_name String last_name String - email String @unique - password String + email String? @unique phone_number Int @unique residence String? role Roles @default(GUEST) diff --git a/src/modules/customers/controllers/customers.controller.ts b/src/modules/customers/controllers/customers.controller.ts new file mode 100644 index 0000000..b30d375 --- /dev/null +++ b/src/modules/customers/controllers/customers.controller.ts @@ -0,0 +1,38 @@ +import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common'; +import { CustomersService } from '../services/customers.service'; +import { Customers, Employees } from '@prisma/client'; +import { CreateCustomerDto } from '../dtos/create-customers'; +import { UpdateCustomerDto } from '../dtos/update-customers'; + +@Controller('customers') +export class CustomersController { + constructor(private readonly customersService: CustomersService) {} + + @Post() + create(@Body() dto: CreateCustomerDto): Promise { + return this.customersService.create(dto); + } + + @Get() + findAll(): Promise { + return this.customersService.findAll(); + } + + @Get(':id') + findOne(@Param('id', ParseIntPipe) id: number): Promise { + return this.customersService.findOne(id); + } + + @Patch(':id') + update( + @Param('id', ParseIntPipe) id: number, + @Body() dto: UpdateCustomerDto, + ): Promise { + return this.customersService.update(id, dto); + } + + @Delete(':id') + remove(@Param('id', ParseIntPipe) id: number): Promise{ + return this.customersService.remove(id); + } +} diff --git a/src/modules/customers/customers.module.ts b/src/modules/customers/customers.module.ts new file mode 100644 index 0000000..c9e3f9d --- /dev/null +++ b/src/modules/customers/customers.module.ts @@ -0,0 +1,10 @@ + +import { Module } from '@nestjs/common'; +import { CustomersController } from './controllers/customers.controller'; +import { CustomersService } from './services/customers.service'; + +@Module({ + controllers:[CustomersController], + providers:[CustomersService], +}) +export class CustomersModule {} \ No newline at end of file diff --git a/src/modules/customers/dtos/create-customers.ts b/src/modules/customers/dtos/create-customers.ts new file mode 100644 index 0000000..4ae03fe --- /dev/null +++ b/src/modules/customers/dtos/create-customers.ts @@ -0,0 +1,37 @@ +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; +} \ No newline at end of file diff --git a/src/modules/customers/dtos/update-customers.ts b/src/modules/customers/dtos/update-customers.ts new file mode 100644 index 0000000..ded8b46 --- /dev/null +++ b/src/modules/customers/dtos/update-customers.ts @@ -0,0 +1,4 @@ +import { PartialType } from "@nestjs/swagger"; +import { CreateCustomerDto } from "./create-customers"; + +export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {} \ No newline at end of file diff --git a/src/modules/customers/services/customers.service.ts b/src/modules/customers/services/customers.service.ts new file mode 100644 index 0000000..8175160 --- /dev/null +++ b/src/modules/customers/services/customers.service.ts @@ -0,0 +1,97 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { CreateCustomerDto } from '../dtos/create-customers'; +import { Customers, Users } from '@prisma/client'; +import { UpdateCustomerDto } from '../dtos/update-customers'; + +@Injectable() +export class CustomersService { + constructor(private readonly prisma: PrismaService) {} + + async create(dto: CreateCustomerDto): Promise { + const { + first_name, + last_name, + email, + phone_number, + residence, + invoice_id, + } = dto; + + return this.prisma.$transaction(async (tx) => { + const user: Users = await tx.users.create({ + data: { + first_name, + last_name, + email, + phone_number, + residence, + }, + }); + return tx.customers.create({ + data: { + user_id: user.id, + invoice_id, + }, + }); + }); + } + + findAll(): Promise { + return this.prisma.customers.findMany({ + include: { user: true }, + }) + } + + async findOne(id:number): Promise { + const customer = await this.prisma.customers.findUnique({ + where: { id }, + include: { user: true }, + }); + if(!customer) { + throw new NotFoundException(`Customer #${id} not found`); + } + return customer; + } + +async update( + id: number, + dto: UpdateCustomerDto, +): Promise { + const customer = await this.findOne(id); + + const { + first_name, + last_name, + email, + phone_number, + residence, + invoice_id, + } = dto; + + return this.prisma.$transaction(async (tx) => { + await tx.users.update({ + where: { id: customer.user_id }, + data: { + ...(first_name !== undefined && { first_name }), + ...(last_name !== undefined && { last_name }), + ...(email !== undefined && { email }), + ...(phone_number !== undefined && { phone_number }), + ...(residence !== undefined && { residence }), + }, + }); + + return tx.customers.update({ + where: { id }, + data: { + ...(invoice_id !== undefined && { invoice_id }), + }, + }); + }); +} + + async remove(id: number): Promise { + await this.findOne(id); + return this.prisma.customers.delete({ where: { id }}); + } +} diff --git a/src/modules/employees/dtos/create-employee.dto.ts b/src/modules/employees/dtos/create-employee.dto.ts index f25217e..5cb7c82 100644 --- a/src/modules/employees/dtos/create-employee.dto.ts +++ b/src/modules/employees/dtos/create-employee.dto.ts @@ -9,7 +9,6 @@ import { IsString, } from 'class-validator'; import { Type } from 'class-transformer'; -import { Roles } from '@prisma/client'; export class CreateEmployeeDto { @IsString() @@ -21,12 +20,8 @@ export class CreateEmployeeDto { last_name: string; @IsEmail() - @IsNotEmpty() - email: string; - - @IsString() - @IsNotEmpty() - password: string; + @IsOptional() + email?: string; @Type(() => Number) @IsInt() @@ -37,10 +32,6 @@ export class CreateEmployeeDto { @IsOptional() residence?: string; - @IsString() - @IsNotEmpty() - role: Roles; - @IsInt() @IsPositive() @Type(() => Number) diff --git a/src/modules/employees/services/employees.service.ts b/src/modules/employees/services/employees.service.ts index 2fb6f43..0842e70 100644 --- a/src/modules/employees/services/employees.service.ts +++ b/src/modules/employees/services/employees.service.ts @@ -1,6 +1,5 @@ import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from 'src/prisma/prisma.service'; -import { UsersService } from 'src/modules/users-management/services/users.service'; import { CreateEmployeeDto } from '../dtos/create-employee.dto'; import { UpdateEmployeeDto } from '../dtos/update-employee.dto'; import { Employees, Users } from '@prisma/client'; @@ -9,7 +8,6 @@ import { Employees, Users } from '@prisma/client'; export class EmployeesService { constructor( private readonly prisma: PrismaService, - private readonly usersService: UsersService, ) {} async create(dto: CreateEmployeeDto): Promise { @@ -17,10 +15,8 @@ export class EmployeesService { first_name, last_name, email, - password, phone_number, residence, - role, external_payroll_id, company_code, first_work_day, @@ -33,10 +29,8 @@ export class EmployeesService { first_name, last_name, email, - password, phone_number, residence, - role, }, }); return tx.employees.create({ @@ -68,22 +62,49 @@ export class EmployeesService { return emp; } - async update( +async update( id: number, dto: UpdateEmployeeDto, ): Promise { - await this.findOne(id); - return this.prisma.employees.update({ - where: { id }, - data: { - external_payroll_id: dto.external_payroll_id, - company_code: dto.company_code, - first_work_day: dto.first_work_day, - last_work_day: dto.last_work_day, - }, + const emp = await this.findOne(id); + + const { + first_name, + last_name, + email, + phone_number, + residence, + external_payroll_id, + company_code, + first_work_day, + last_work_day, + } = dto; + + return this.prisma.$transaction(async (tx) => { + await tx.users.update({ + where: { id: emp.user_id }, + data: { + ...(first_name !== undefined && { first_name }), + ...(last_name !== undefined && { last_name }), + ...(email !== undefined && { email }), + ...(phone_number !== undefined && { phone_number }), + ...(residence !== undefined && { residence }), + }, + }); + + return tx.employees.update({ + where: { id }, + data: { + ...(external_payroll_id !== undefined && { external_payroll_id }), + ...(company_code !== undefined && { company_code }), + ...(first_work_day !== undefined && { first_work_day }), + ...(last_work_day !== undefined && { last_work_day }), + }, + }); }); } + async remove(id: number): Promise { await this.findOne(id); return this.prisma.employees.delete({ where: { id } }); diff --git a/src/modules/leave_requests/dtos/create-leave-requests.dto.ts b/src/modules/leave_requests/dtos/create-leave-requests.dto.ts index e69de29..7f7ade2 100644 --- a/src/modules/leave_requests/dtos/create-leave-requests.dto.ts +++ b/src/modules/leave_requests/dtos/create-leave-requests.dto.ts @@ -0,0 +1,3 @@ +export class CreateLeaveRequestsDto { + +} \ No newline at end of file diff --git a/src/modules/leave_requests/dtos/update-leave-requests.dto.ts b/src/modules/leave_requests/dtos/update-leave-requests.dto.ts index e69de29..ba67760 100644 --- a/src/modules/leave_requests/dtos/update-leave-requests.dto.ts +++ b/src/modules/leave_requests/dtos/update-leave-requests.dto.ts @@ -0,0 +1,3 @@ +export class UpdateLeaveRequestsDto { + +} \ No newline at end of file diff --git a/src/modules/shift-codes/dtos/create-shift-codes.dto.ts b/src/modules/shift-codes/dtos/create-shift-codes.dto.ts new file mode 100644 index 0000000..f92d04d --- /dev/null +++ b/src/modules/shift-codes/dtos/create-shift-codes.dto.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty, IsString } from "class-validator"; + +export class CreateShiftCodesDto { + @IsString() + @IsNotEmpty() + shift_type: string; + + @IsString() + @IsNotEmpty() + bank_code: string; +} \ No newline at end of file diff --git a/src/modules/shift-codes/dtos/update-shift-codes.dto.ts b/src/modules/shift-codes/dtos/update-shift-codes.dto.ts new file mode 100644 index 0000000..93f5c3f --- /dev/null +++ b/src/modules/shift-codes/dtos/update-shift-codes.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateShiftCodesDto } from './create-shift-codes.dto'; + +export class UpdateShiftCodesDto extends PartialType(CreateShiftCodesDto) {} diff --git a/src/modules/shift-codes/services/shift-codes.service.ts b/src/modules/shift-codes/services/shift-codes.service.ts index e69de29..5d0d8c8 100644 --- a/src/modules/shift-codes/services/shift-codes.service.ts +++ b/src/modules/shift-codes/services/shift-codes.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from "@nestjs/common"; +import { PrismaService } from "src/prisma/prisma.service"; +import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto"; +import { ShiftCodes } from "@prisma/client"; + +@Injectable() +export class ShiftCodesService { + constructor(private readonly prisma: PrismaService) {} + + create(dto: CreateShiftCodesDto): Promise { + const { + shift_type, + bank_code, + } = dto; + return this.prisma.$queryRaw(dto) + } +} \ 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 e69de29..c53cfa8 100644 --- a/src/modules/shifts/controllers/shifts.controller.ts +++ b/src/modules/shifts/controllers/shifts.controller.ts @@ -0,0 +1,6 @@ +import { Controller } from "@nestjs/common"; + +@Controller('shifts') +export class ShiftsController { + +} \ 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 e69de29..4a15280 100644 --- a/src/modules/shifts/dtos/create-shifts.dto.ts +++ b/src/modules/shifts/dtos/create-shifts.dto.ts @@ -0,0 +1,19 @@ +import { Type } from "class-transformer"; +import { IsDate, IsDateString } from "class-validator"; + +export class CreateShiftDto { + @IsDateString() + @Type(() => Date) + @IsDate() + date: Date; + + @IsDateString() + @Type(() => Date) + @IsDate() + start_time: Date; + + @IsDateString() + @Type(() => Date) + @IsDate() + end_time: Date; +} \ No newline at end of file diff --git a/src/modules/shifts/dtos/update-shifts.dto.ts b/src/modules/shifts/dtos/update-shifts.dto.ts index e69de29..8b10139 100644 --- a/src/modules/shifts/dtos/update-shifts.dto.ts +++ b/src/modules/shifts/dtos/update-shifts.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from "@nestjs/swagger"; +import { CreateShiftDto } from "./create-shifts.dto"; + +export class UpdateShiftsDto extends PartialType(CreateShiftDto){} \ No newline at end of file diff --git a/src/modules/shifts/services/shifts.service.ts b/src/modules/shifts/services/shifts.service.ts index e69de29..3443cbc 100644 --- a/src/modules/shifts/services/shifts.service.ts +++ b/src/modules/shifts/services/shifts.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from "@nestjs/common"; +import { TimesheetsService } from "src/modules/timesheets/services/timesheets.service"; +import { PrismaService } from "src/prisma/prisma.service"; +import { CreateShiftDto } from "../dtos/create-shifts.dto"; +import { Shifts } from "@prisma/client"; + +@Injectable() +export class ShiftsService { + constructor( + private readonly prisma: PrismaService, + private readonly timesheetsService: TimesheetsService, + + ) {} +} \ No newline at end of file diff --git a/src/modules/shifts/shifts.module.ts b/src/modules/shifts/shifts.module.ts index e69de29..b63b08c 100644 --- a/src/modules/shifts/shifts.module.ts +++ b/src/modules/shifts/shifts.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ShiftsController } from './controllers/shifts.controller'; +import { ShiftsService } from './services/shifts.service'; + +@Module({ + controllers: [ShiftsController], + providers: [ShiftsService] +}) +export class ShiftsModule {}