feat(employees): CRUD employees et refactor users unto abstract class

This commit is contained in:
Matthieu Haineault 2025-07-15 16:26:42 -04:00
parent dc3fac76c1
commit 00d845294d
15 changed files with 245 additions and 98 deletions

View File

@ -20,7 +20,6 @@ model Users {
email String? @unique
phone_number Int @unique
residence String?
role Roles @default(USER)
employee Employees? @relation("UserEmployee")
@ -53,7 +52,6 @@ model Customers {
}
enum Roles {
USER
ADMIN
CUSTOMER
DEALER

View File

@ -1,15 +1,15 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UsersController } from './users.controller';
import { EmployeesController } from './employees.controller';
describe('UsersController', () => {
let controller: UsersController;
describe('EmployeesController', () => {
let controller: EmployeesController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [UsersController],
controllers: [EmployeesController],
}).compile();
controller = module.get<UsersController>(UsersController);
controller = module.get<EmployeesController>(EmployeesController);
});
it('should be defined', () => {

View File

@ -0,0 +1,51 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
} from '@nestjs/common';
import { Employees } from '@prisma/client';
import { EmployeesService } from '../services/employees.service';
import { CreateEmployeeDto } from '../dtos/create-employee.dto';
import { UpdateEmployeeDto } from '../dtos/update-employee.dto';
@Controller('employees')
export class EmployeesController {
constructor(private readonly employeesService: EmployeesService) {}
@Post()
create(@Body() dto: CreateEmployeeDto): Promise<Employees> {
return this.employeesService.create(dto);
}
@Get()
findAll(): Promise<Employees[]> {
return this.employeesService.findAll();
}
@Get(':employee_id')
findOne(
@Param('employee_id', ParseIntPipe) employee_id: number,
): Promise<Employees> {
return this.employeesService.findOne(employee_id);
}
@Patch(':employee_id')
update(
@Param('employee_id', ParseIntPipe) employee_id: number,
@Body() dto: UpdateEmployeeDto,
): Promise<Employees> {
return this.employeesService.update(employee_id, dto);
}
@Delete(':employee_id')
remove(
@Param('employee_id', ParseIntPipe) employee_id: number,
): Promise<Employees> {
return this.employeesService.remove(employee_id);
}
}

View File

@ -0,0 +1,57 @@
import {
IsDate,
IsDateString,
IsEmail,
IsInt,
IsNotEmpty,
IsOptional,
IsPositive,
IsString,
} from 'class-validator';
import { Type } from 'class-transformer';
export class CreateEmployeeDto {
@IsString()
@IsNotEmpty()
first_name: string;
@IsString()
@IsNotEmpty()
last_name: string;
@IsEmail()
@IsOptional()
email?: string;
@Type(() => Number)
@IsInt({
message: 'Le numéro de téléphone doit être sans tirets ni espaces.',
})
@IsPositive()
phone_number: number;
@IsString()
@IsOptional()
residence?: string;
@IsInt()
@IsPositive()
@Type(() => Number)
external_payroll_id: number;
@IsInt()
@IsPositive()
@Type(() => Number)
company_code: number;
@IsDateString()
@Type(() => Date)
@IsDate()
first_work_day: Date;
@IsDateString()
@Type(() => Date)
@IsDate()
@IsOptional()
last_work_day?: Date;
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateEmployeeDto } from './create-employee.dto';
export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) {}

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { EmployeesController } from './controllers/employees.controller';
import { EmployeesService } from './services/employees.service';
@Module({
controllers: [EmployeesController],
providers: [EmployeesService],
})
export class EmployeesModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { EmployeesService } from './employees.service';
describe('EmployeesService', () => {
let service: EmployeesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [EmployeesService],
}).compile();
service = module.get<EmployeesService>(EmployeesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -0,0 +1,87 @@
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';
@Injectable()
export class EmployeesService {
constructor(
private readonly prisma: PrismaService,
private readonly usersService: UsersService,
) {}
async create(dto: CreateEmployeeDto): Promise<Employees> {
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) => {
const user: Users = await tx.users.create({
data: {
first_name,
last_name,
email,
phone_number,
residence,
},
});
return tx.employees.create({
data: {
user_id: user.user_id,
external_payroll_id,
company_code,
first_work_day,
last_work_day,
},
});
});
}
findAll(): Promise<Employees[]> {
return this.prisma.employees.findMany({
include: { user: true },
});
}
async findOne(employee_id: number): Promise<Employees> {
const emp = await this.prisma.employees.findUnique({
where: { employee_id },
include: { user: true },
});
if (!emp) {
throw new NotFoundException(`Employee #${employee_id} not found`);
}
return emp;
}
async update(
employee_id: number,
dto: UpdateEmployeeDto,
): Promise<Employees> {
await this.findOne(employee_id);
return this.prisma.employees.update({
where: { employee_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,
},
});
}
async remove(employee_id: number): Promise<Employees> {
await this.findOne(employee_id);
return this.prisma.employees.delete({ where: { employee_id } });
}
}

View File

@ -1,16 +1,10 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateUserDto } from '../dtos/create-user.dto';
import { UpdateUserDto } from '../dtos/update-user.dto';
import { PrismaService } from 'src/prisma/prisma.service';
import { Users } from '@prisma/client';
import { PrismaService } from 'src/prisma/prisma.service';
@Injectable()
export class UsersService {
constructor(private readonly prisma: PrismaService) {}
create(dto: CreateUserDto): Promise<Users> {
return this.prisma.users.create({ data: dto });
}
export abstract class AbstractUserService {
constructor(protected readonly prisma: PrismaService) {}
findAll(): Promise<Users[]> {
return this.prisma.users.findMany();
@ -24,14 +18,6 @@ export class UsersService {
return user;
}
async update(user_id: number, dto: UpdateUserDto): Promise<Users> {
await this.findOne(user_id);
return this.prisma.users.update({
where: { user_id },
data: dto,
});
}
async remove(user_id: number): Promise<Users> {
await this.findOne(user_id);
return this.prisma.users.delete({ where: { user_id } });

View File

@ -0,0 +1,10 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { AbstractUserService } from './abstract-user.service';
@Injectable()
export class UsersService extends AbstractUserService {
constructor(protected readonly prisma: PrismaService) {
super(prisma);
}
}

View File

@ -1,11 +1,10 @@
import { Module } from '@nestjs/common';
import { UsersService } from './services/users.service';
import { UsersController } from './controllers/users.controller';
import { PrismaModule } from 'src/prisma/prisma.module';
@Module({
imports: [PrismaModule],
providers: [UsersService],
controllers: [UsersController],
controllers: [],
})
export class UsersModule {}

View File

@ -1,47 +0,0 @@
import {
Controller,
Get,
Post,
Body,
Param,
Patch,
Delete,
ParseIntPipe,
} from '@nestjs/common';
import { UsersService } from '../services/users.service';
import { CreateUserDto } from '../dtos/create-user.dto';
import { UpdateUserDto } from '../dtos/update-user.dto';
import { Users } from '@prisma/client';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() dto: CreateUserDto): Promise<Users> {
return this.usersService.create(dto);
}
@Get()
findAll(): Promise<Users[]> {
return this.usersService.findAll();
}
@Get()
findOne(@Param('id', ParseIntPipe) user_id: number): Promise<Users> {
return this.usersService.findOne(user_id);
}
@Patch(':user_id')
update(
@Param('user_id', ParseIntPipe) user_id: number,
@Body() dto: UpdateUserDto,
): Promise<Users> {
return this.usersService.update(user_id, dto);
}
@Delete(':user_id')
remove(@Param('user_id', ParseIntPipe) user_id: number): Promise<Users> {
return this.usersService.remove(user_id);
}
}

View File

@ -1,21 +0,0 @@
import { IsString, IsNotEmpty, IsEmail, IsPhoneNumber } from 'class-validator';
export class CreateUserDto {
@IsString()
@IsNotEmpty()
first_name: string;
@IsString()
@IsNotEmpty()
last_name: string;
@IsEmail()
email: string;
@IsPhoneNumber()
@IsNotEmpty()
phone_number: number;
@IsString()
residence: string;
}

View File

@ -1,4 +0,0 @@
import { PartialType } from '@nestjs/swagger';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}