feat(modules): timesheets, shifts, shift-codes and minor fix in employees

This commit is contained in:
Matthieu Haineault 2025-07-17 13:14:33 -04:00
parent acf8d04945
commit 5996e0c389
18 changed files with 423 additions and 32 deletions

View File

@ -10,7 +10,7 @@ generator client {
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
url = env("DATABASE_URL_DEV")
}
model Users {

View File

@ -1,8 +1,8 @@
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';
import { CreateCustomerDto } from '../dtos/create-customer';
import { UpdateCustomerDto } from '../dtos/update-customer';
@Controller('customers')
export class CustomersController {

View File

@ -1,4 +1,4 @@
import { PartialType } from "@nestjs/swagger";
import { CreateCustomerDto } from "./create-customers";
import { CreateCustomerDto } from "./create-customer";
export class UpdateCustomerDto extends PartialType(CreateCustomerDto) {}

View File

@ -1,8 +1,8 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateCustomerDto } from '../dtos/create-customers';
import { CreateCustomerDto } from '../dtos/create-customer';
import { Customers, Users } from '@prisma/client';
import { UpdateCustomerDto } from '../dtos/update-customers';
import { UpdateCustomerDto } from '../dtos/update-customer';
@Injectable()
export class CustomersService {

View File

@ -21,7 +21,7 @@ export class CreateEmployeeDto {
@IsEmail()
@IsOptional()
email?: string;
email: string;
@Type(() => Number)
@IsInt()

View File

@ -6,9 +6,7 @@ import { Employees, Users } from '@prisma/client';
@Injectable()
export class EmployeesService {
constructor(
private readonly prisma: PrismaService,
) {}
constructor(private readonly prisma: PrismaService) {}
async create(dto: CreateEmployeeDto): Promise<Employees> {
const {

View File

@ -0,0 +1,36 @@
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
import { ShiftCodesService } from "../services/shift-codes.service";
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
@Controller()
export class ShiftCodesController {
constructor(private readonly shiftCodesService: ShiftCodesService) {}
@Post()
create(@Body()dto: CreateShiftCodesDto): Promise<ShiftCodes> {
return this.shiftCodesService.create(dto);
}
@Get()
findAll(): Promise<ShiftCodes[]> {
return this.shiftCodesService.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number): Promise<ShiftCodes> {
return this.shiftCodesService.findOne(id);
}
@Patch(':id')
update(@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateShiftCodesDto): Promise<ShiftCodes> {
return this.shiftCodesService.update(id,dto);
}
@Delete(':id')
remove(@Param('id', ParseIntPipe)id: number): Promise<ShiftCodes> {
return this.shiftCodesService.remove(id);
}
}

View File

@ -1,17 +1,109 @@
import { Injectable } from "@nestjs/common";
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateShiftCodesDto } from "../dtos/create-shift-codes.dto";
import { ShiftCodes } from "@prisma/client";
import { UpdateShiftCodesDto } from "../dtos/update-shift-codes.dto";
@Injectable()
export class ShiftCodesService {
constructor(private readonly prisma: PrismaService) {}
create(dto: CreateShiftCodesDto): Promise<ShiftCodes> {
const {
shift_type,
bank_code,
} = dto;
return this.prisma.$queryRaw(dto)
async create(dto: CreateShiftCodesDto): 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: UpdateShiftCodesDto): 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

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

View File

@ -1,6 +1,40 @@
import { Controller } from "@nestjs/common";
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
import { ShiftsService } from "../services/shifts.service";
import { Shifts } from "@prisma/client";
import { UpdateEmployeeDto } from "src/modules/employees/dtos/update-employee.dto";
import { CreateShiftDto } from "../dtos/create-shifts.dto";
@Controller('shifts')
export class ShiftsController {
constructor(private readonly shiftsService: ShiftsService){}
@Post()
create(@Body() dto: CreateShiftDto): Promise<Shifts> {
return this.shiftsService.create(dto);
}
@Get()
findAll(): Promise<Shifts[]> {
return this.shiftsService.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
return this.shiftsService.findOne(id);
}
@Patch(':id')
update(
@Param('id', ParseIntPipe) id: number,
@Body() dto: UpdateEmployeeDto,
): Promise<Shifts> {
return this.shiftsService.update(id, dto);
}
@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number): Promise<Shifts> {
return this.shiftsService.remove(id);
}
}

View File

@ -1,7 +1,16 @@
import { Type } from "class-transformer";
import { IsDate, IsDateString } from "class-validator";
import { IsDate, IsDateString, IsInt } from "class-validator";
export class CreateShiftDto {
@Type(() => Number)
@IsInt()
timesheet_id: number;
@Type(() => Number)
@IsInt()
shift_code_id: number;
@IsDateString()
@Type(() => Date)
@IsDate()

View File

@ -1,14 +1,101 @@
import { Injectable } from "@nestjs/common";
import { TimesheetsService } from "src/modules/timesheets/services/timesheets.service";
import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { CreateShiftDto } from "../dtos/create-shifts.dto";
import { Shifts } from "@prisma/client";
import { notDeepEqual } from "assert";
import { UpdateShiftsDto } from "../dtos/update-shifts.dto";
@Injectable()
export class ShiftsService {
constructor(
private readonly prisma: PrismaService,
private readonly timesheetsService: TimesheetsService,
constructor(private readonly prisma: PrismaService) {}
) {}
async create(dto: CreateShiftDto): Promise<Shifts> {
const {
timesheet_id,
shift_code_id,
date,
start_time,
end_time
} = dto;
return this.prisma.shifts.create({
data: {
timesheet_id,
shift_code_id,
date, start_time,
end_time
},
include: {
timesheet: {
include: {
employee: {
include: { user: true }
},
},
shift_code: true,
},
},
});
}
findAll(): Promise<Shifts[]> {
return this.prisma.shifts.findMany({
include: {
timesheet: {
include: {
employee: { user:true }
},
},
},
});
}
async findOne(id: number): Promise<Shifts> {
const shift = await this.prisma.shifts.findUnique({
where: { id },
include: {
timesheet: {
include: {
employee: { user: true }
},
},
shift_code: true,
},
});
if(!shift) {
throw new NotFoundException(`Shift #${id} not found`);
}
return shift;
}
async update(
id: number,
dto: UpdateShiftsDto,
): Promise<Shifts> {
await this.prisma.shifts.update({
where: { id },
data: {
...(timesheets_id !== undefined && { timesheet_id }),
...(shift_code_id !== undefined && { shift_code_id }),
...(date !== undefined && { date }),
...(start_time !== undefined && { start_time }),
...(end_time !== undefined && { end_time }),
},
include: {
timesheet: {
include: {
employee: {
include: { user: true }
},
},
shift_code: true,
},
},
});
}
async remove(id: number): Promise<Shifts> {
await this.findOne(id);
return this.prisma.shifts.delete({ where: { id } });
}
}

View File

@ -1,9 +1,10 @@
import { Module } from '@nestjs/common';
import { ShiftsController } from './controllers/shifts.controller';
import { ShiftsService } from './services/shifts.service';
import { PrismaService } from 'src/prisma/prisma.service';
@Module({
controllers: [ShiftsController],
providers: [ShiftsService]
providers: [ShiftsService, PrismaService]
})
export class ShiftsModule {}

View File

@ -1,4 +1,38 @@
import { Controller } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Patch, Post } from '@nestjs/common';
import { TimesheetsService } from '../services/timesheets.service';
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
import { Timesheets } from '@prisma/client';
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
@Controller('timesheets')
export class TimesheetsController {}
export class TimesheetsController {
constructor(private readonly timesheetsService: TimesheetsService) {}
@Post()
create(@Body() dto: CreateTimesheetDto): Promise<Timesheets> {
return this.timesheetsService.create(dto);
}
@Get()
findAll(): Promise<Timesheets[]> {
return this.timesheetsService.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
return this.timesheetsService.findOne(id);
}
@Patch(':id')
update(
@Param('id', ParseIntPipe) id:number,
@Body() dto: UpdateTimesheetDto,
): Promise<Timesheets> {
return this.timesheetsService.update(id, dto);
}
@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number): Promise<Timesheets> {
return this.timesheetsService.remove(id);
}
}

View File

@ -1 +1,13 @@
export class CreateTimesheetDto {}
import { Type } from "class-transformer";
import { IsBoolean, IsInt, IsOptional } from "class-validator";
export class CreateTimesheetDto {
@Type(() => Number)
@IsInt()
employee_id: number;
@IsOptional()
@IsBoolean()
is_approved?: boolean;
}

View File

@ -1 +1,4 @@
export class UpdateTimesheetDto {}
import { PartialType } from "@nestjs/swagger";
import { CreateTimesheetDto } from "./create-timesheet.dto";
export class UpdateTimesheetDto extends PartialType(CreateTimesheetDto) {}

View File

@ -1,4 +1,78 @@
import { Injectable } from '@nestjs/common';
import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateTimesheetDto } from '../dtos/create-timesheet.dto';
import { Timesheets } from '@prisma/client';
import { UpdateTimesheetDto } from '../dtos/update-timesheet.dto';
@Injectable()
export class TimesheetsService {}
export class TimesheetsService {
constructor(private readonly prisma: PrismaService) {}
async create(dto : CreateTimesheetDto): Promise<Timesheets> {
const { employee_id, is_approved } = dto;
return this.prisma.timesheets.create({
data: {
employee_id,
is_approved: is_approved ?? false,
},
include: {
employee: {
include: { user: true }
},
},
});
}
findAll(): Promise<Timesheets[]> {
return this.prisma.timesheets.findMany({
include: {
employee: {
include: { user: true },
},
},
});
}
async findOne(id: number): Promise<Timesheets> {
const record = await this.prisma.timesheets.findUnique({
where: { id },
include: {
employee: {
include: {
user:true
}
},
},
});
if(!record) {
throw new NotFoundException(`Timesheet #${id} not found`);
}
return record;
}
async update(id: number, dto:UpdateTimesheetDto): Promise<Timesheets> {
await this.findOne(id);
const { employee_id, is_approved } = dto;
return this.prisma.timesheets.update({
where: { id },
data: {
...(employee_id !== undefined && { employee_id }),
...(is_approved !== undefined && { is_approved }),
},
include: {
employee: {
include: { user: true }
},
},
});
}
async remove(id: number): Promise<Timesheets> {
await this.findOne(id);
return this.prisma.timesheets.delete({
where: { id },
});
}
}