feat(shifts): extract delete logics outside of master upsert method and create a new route for delete requests

This commit is contained in:
Matthieu Haineault 2025-10-14 10:35:30 -04:00
parent d95b6471cd
commit 99e9f1f3bf
4 changed files with 66 additions and 15 deletions

View File

@ -483,6 +483,52 @@
]
}
},
"/shifts/{email}/{date}": {
"delete": {
"operationId": "ShiftsController_remove",
"parameters": [
{
"name": "email",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
},
{
"name": "date",
"required": true,
"in": "path",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpsertShiftDto"
}
}
}
},
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"access-token": []
}
],
"tags": [
"Shifts"
]
}
},
"/shifts/approval/{id}": {
"patch": {
"operationId": "ShiftsController_approve",

View File

@ -1,11 +1,11 @@
import { Body, Controller, Get, Header, Param, ParseBoolPipe, ParseIntPipe, Patch, Put, Query, } from "@nestjs/common";
import { Body, Controller, Delete, Get, Header, Param, ParseBoolPipe, ParseIntPipe, Patch, Put, Query, } from "@nestjs/common";
import { RolesAllowed } from "src/common/decorators/roles.decorators";
import { Roles as RoleEnum } from '.prisma/client';
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
import { ShiftsCommandService } from "../services/shifts-command.service";
import { ShiftsQueryService } from "../services/shifts-query.service";
import { GetShiftsOverviewDto } from "../dtos/get-shift-overview.dto";
import { UpsertShiftDto } from "../dtos/upsert-shift.dto";
import { ShiftPayloadDto, UpsertShiftDto } from "../dtos/upsert-shift.dto";
import { OverviewRow } from "../types-and-interfaces/shifts-overview-row.interface";
import { UpsertAction } from "src/modules/shared/types/upsert-actions.types";
@ -28,6 +28,15 @@ export class ShiftsController {
return this.shiftsCommandService.upsertShifts(email_param, action, payload);
}
@Delete(':email/:date')
async remove(
@Param('email') email: string,
@Param('date') date: string,
@Body() payload: UpsertShiftDto,
) {
return this.shiftsCommandService.deleteShift(email, date, payload);
}
@Patch('approval/:id')
//@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
async approve(@Param('id', ParseIntPipe) id: number, @Body('is_approved', ParseBoolPipe) isApproved: boolean) {
@ -74,4 +83,5 @@ export class ShiftsController {
return Buffer.from('\uFEFF' + header + body, 'utf8');
}
}

View File

@ -10,8 +10,8 @@ export function toDateOnly(ymd: string): Date {
return new Date(y, m, d, 0, 0, 0, 0);
}
export function weekStartSunday(dateLocal: Date): Date {
const start = new Date(dateLocal.getFullYear(), dateLocal.getMonth(), dateLocal.getDate());
export function weekStartSunday(date_local: Date): Date {
const start = new Date(date_local.getFullYear(), date_local.getMonth(), date_local.getDate());
const dow = start.getDay(); // 0 = dimanche
start.setDate(start.getDate() - dow);
start.setHours(0, 0, 0, 0);

View File

@ -69,12 +69,6 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
}
return this.updateShift(employee_id, date, dto);
}
if(action === 'delete'){
if(!dto.old_shift || dto.new_shift) {
throw new BadRequestException('Only old_shift must be provided for delete');
}
return this.deleteShift(employee_id, date, dto);
}
throw new BadRequestException(`Unknown action: ${action}`);
}
@ -164,13 +158,14 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
//_________________________________________________________________
// DELETE
//_________________________________________________________________
private async deleteShift(
employee_id: number,
async deleteShift(
email: string,
date_iso: string,
dto: UpsertShiftDto,
): Promise<{ action: UpsertAction; day: DayShiftResponse[]; }>{
): Promise<{ day: DayShiftResponse[]; }>{
return this.prisma.$transaction(async (tx) => {
const date_only = toDateOnly(date_iso);
const date_only = toDateOnly(date_iso);
const employee_id = await this.emailResolver.findIdByEmail(email);
const { id: timesheet_id } = await this.helpersService.ensureTimesheet(tx, employee_id, date_only);
const old_norm_shift = await this.helpersService.normalizeRequired(dto.old_shift, 'old_shift');
@ -188,7 +183,7 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
await this.helpersService.afterWriteOvertimeAndLog(tx, employee_id, date_only, 'delete');
const fresh_shift = await this.helpersService.getDayShifts(tx, timesheet_id, date_iso);
return { action: 'delete', day: await this.helpersService.mapDay(fresh_shift)};
return { day: await this.helpersService.mapDay(fresh_shift)};
});
}
}