fix(schedule-preset): adjust services to use consistent dto and field names (mix of shifts and preset_shifts)

This commit is contained in:
Nic D. 2025-12-10 16:51:38 -05:00
parent b6132c8b35
commit cb52089db8
7 changed files with 260 additions and 227 deletions

View File

@ -1,9 +1,3 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client { generator client {
provider = "prisma-client-js" provider = "prisma-client-js"
previewFeatures = ["views"] previewFeatures = ["views"]
@ -15,14 +9,13 @@ datasource db {
} }
model Users { model Users {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
first_name String first_name String
last_name String last_name String
email String @unique email String @unique
phone_number String phone_number String
residence String? residence String?
role Roles @default(GUEST) role Roles @default(GUEST)
employee Employees? @relation("UserEmployee") employee Employees? @relation("UserEmployee")
oauth_sessions OAuthSessions[] @relation("UserOAuthSessions") oauth_sessions OAuthSessions[] @relation("UserOAuthSessions")
preferences Preferences? @relation("UserPreferences") preferences Preferences? @relation("UserPreferences")
@ -32,58 +25,53 @@ model Users {
} }
model userModuleAccess { model userModuleAccess {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
user Users @relation("UserModuleAccess", fields: [user_id], references: [id]) user_id String @unique @db.Uuid
user_id String @unique @db.Uuid timesheets Boolean @default(false)
timesheets_approval Boolean @default(false)
timesheets Boolean @default(false) //wich allows an employee to enter shifts and expenses employee_list Boolean @default(false)
timesheets_approval Boolean @default(false) //wich allows the approbation of timesheets by a supervisor or above employee_management Boolean @default(false)
employee_list Boolean @default(false) //wich shows the lists of employee to show names, emails, titles and profile picture personal_profile Boolean @default(false)
employee_management Boolean @default(false) //wich offers CRUD for employees, schedule_presets and manage module access dashboard Boolean @default(false)
personal_profile Boolean @default(false) //wich governs profile details, preferances and dashboard access user Users @relation("UserModuleAccess", fields: [user_id], references: [id])
dashboard Boolean @default(false) //wich allows access to the main page of the app
@@map("user_module_access") @@map("user_module_access")
} }
model Employees { model Employees {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
user Users @relation("UserEmployee", fields: [user_id], references: [id]) user_id String @unique @db.Uuid
user_id String @unique @db.Uuid
supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
supervisor_id Int?
schedule_preset SchedulePresets? @relation("EmployeesSchedulePreset", fields: [schedule_preset_id], references: [id])
schedule_preset_id Int?
external_payroll_id Int external_payroll_id Int
company_code Int company_code Int
first_work_day DateTime @db.Date first_work_day DateTime @db.Date
last_work_day DateTime? @db.Date last_work_day DateTime? @db.Date
supervisor_id Int?
job_title String? job_title String?
is_supervisor Boolean @default(false) is_supervisor Boolean @default(false)
schedule_preset_id Int?
crew Employees[] @relation("EmployeeSupervisor") schedule_preset SchedulePresets? @relation("EmployeesSchedulePreset", fields: [schedule_preset_id], references: [id])
timesheet Timesheets[] @relation("TimesheetEmployee") supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id])
leave_request LeaveRequests[] @relation("LeaveRequestEmployee") crew Employees[] @relation("EmployeeSupervisor")
user Users @relation("UserEmployee", fields: [user_id], references: [id])
leave_request LeaveRequests[] @relation("LeaveRequestEmployee")
timesheet Timesheets[] @relation("TimesheetEmployee")
@@map("employees") @@map("employees")
} }
model LeaveRequests { model LeaveRequests {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
employee Employees @relation("LeaveRequestEmployee", fields: [employee_id], references: [id]) employee_id Int
employee_id Int
bank_code BankCodes @relation("LeaveRequestBankCodes", fields: [bank_code_id], references: [id])
bank_code_id Int
comment String
dates DateTime[] @db.Date
payable_hours Decimal? @db.Decimal(5, 2)
requested_hours Decimal? @db.Decimal(5, 2)
approval_status LeaveApprovalStatus @default(PENDING)
leave_type LeaveTypes leave_type LeaveTypes
comment String
archive LeaveRequestsArchive[] @relation("LeaveRequestToArchive") approval_status LeaveApprovalStatus @default(PENDING)
bank_code_id Int
payable_hours Decimal? @db.Decimal(5, 2)
requested_hours Decimal? @db.Decimal(5, 2)
dates DateTime[] @db.Date
bank_code BankCodes @relation("LeaveRequestBankCodes", fields: [bank_code_id], references: [id])
employee Employees @relation("LeaveRequestEmployee", fields: [employee_id], references: [id])
archive LeaveRequestsArchive? @relation("LeaveRequestToArchive")
@@unique([employee_id, leave_type, dates], name: "leave_per_employee_date") @@unique([employee_id, leave_type, dates], name: "leave_per_employee_date")
@@index([employee_id, dates]) @@index([employee_id, dates])
@ -91,47 +79,31 @@ model LeaveRequests {
} }
model LeaveRequestsArchive { model LeaveRequestsArchive {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
leave_request LeaveRequests @relation("LeaveRequestToArchive", fields: [leave_request_id], references: [id]) leave_request_id Int @unique
leave_request_id Int archived_at DateTime @default(now())
employee_id Int
leave_type LeaveTypes
comment String
approval_status LeaveApprovalStatus
date DateTime @db.Date
payable_hours Decimal? @db.Decimal(5, 2)
requested_hours Decimal? @db.Decimal(5, 2)
leave_request LeaveRequests @relation("LeaveRequestToArchive", fields: [leave_request_id], references: [id])
archived_at DateTime @default(now())
employee_id Int
date DateTime @db.Date
payable_hours Decimal? @db.Decimal(5, 2)
requested_hours Decimal? @db.Decimal(5, 2)
comment String
leave_type LeaveTypes
approval_status LeaveApprovalStatus
@@unique([leave_request_id])
@@index([employee_id, date]) @@index([employee_id, date])
@@map("leave_requests_archive") @@map("leave_requests_archive")
} }
//pay-period vue
view PayPeriods {
pay_year Int
pay_period_no Int
label String
payday DateTime @db.Date
period_start DateTime @db.Date
period_end DateTime @db.Date
@@map("pay_period")
}
model Timesheets { model Timesheets {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
employee Employees @relation("TimesheetEmployee", fields: [employee_id], references: [id])
employee_id Int employee_id Int
is_approved Boolean @default(false)
start_date DateTime @db.Date start_date DateTime @db.Date
is_approved Boolean @default(false) expense Expenses[] @relation("ExpensesTimesheet")
shift Shifts[] @relation("ShiftTimesheet")
shift Shifts[] @relation("ShiftTimesheet") employee Employees @relation("TimesheetEmployee", fields: [employee_id], references: [id])
expense Expenses[] @relation("ExpensesTimesheet") archive TimesheetsArchive[] @relation("TimesheetsToArchive")
archive TimesheetsArchive[] @relation("TimesheetsToArchive")
@@unique([employee_id, start_date], name: "employee_id_start_date") @@unique([employee_id, start_date], name: "employee_id_start_date")
@@map("timesheets") @@map("timesheets")
@ -139,194 +111,181 @@ model Timesheets {
model TimesheetsArchive { model TimesheetsArchive {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
timesheet Timesheets @relation("TimesheetsToArchive", fields: [timesheet_id], references: [id])
timesheet_id Int timesheet_id Int
archive_at DateTime @default(now())
employee_id Int employee_id Int
is_approved Boolean is_approved Boolean
archive_at DateTime @default(now()) timesheet Timesheets @relation("TimesheetsToArchive", fields: [timesheet_id], references: [id])
@@map("timesheets_archive") @@map("timesheets_archive")
} }
model SchedulePresets { model SchedulePresets {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String name String
is_default Boolean @default(false) is_default Boolean @default(false)
employees Employees[] @relation("EmployeesSchedulePreset")
shifts SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset") shifts SchedulePresetShifts[] @relation("SchedulePresetShiftsSchedulePreset")
employees Employees[] @relation("EmployeesSchedulePreset")
@@map("schedule_presets") @@map("schedule_presets")
} }
model SchedulePresetShifts { model SchedulePresetShifts {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
preset SchedulePresets @relation("SchedulePresetShiftsSchedulePreset", fields: [preset_id], references: [id])
preset_id Int preset_id Int
bank_code BankCodes @relation("SchedulePresetShiftsBankCodes", fields: [bank_code_id], references: [id])
bank_code_id Int bank_code_id Int
sort_order Int
start_time DateTime @db.Time(0)
end_time DateTime @db.Time(0)
is_remote Boolean @default(false)
week_day Weekday
bank_code BankCodes @relation("SchedulePresetShiftsBankCodes", fields: [bank_code_id], references: [id])
preset SchedulePresets @relation("SchedulePresetShiftsSchedulePreset", fields: [preset_id], references: [id])
start_time DateTime @db.Time(0) @@unique([preset_id, week_day, sort_order])
end_time DateTime @db.Time(0)
is_remote Boolean @default(false)
week_day Weekday
@@unique([preset_id, week_day], name: "unique_preset_shift_per_day")
@@index([preset_id, week_day]) @@index([preset_id, week_day])
@@map("schedule_preset_shifts") @@map("schedule_preset_shifts")
} }
model Shifts { model Shifts {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
timesheet Timesheets @relation("ShiftTimesheet", fields: [timesheet_id], references: [id])
timesheet_id Int timesheet_id Int
bank_code BankCodes @relation("ShiftBankCodes", fields: [bank_code_id], references: [id]) date DateTime @db.Date
start_time DateTime @db.Time(0)
end_time DateTime @db.Time(0)
bank_code_id Int bank_code_id Int
is_approved Boolean @default(false)
date DateTime @db.Date is_remote Boolean @default(false)
start_time DateTime @db.Time(0) comment String?
end_time DateTime @db.Time(0) bank_code BankCodes @relation("ShiftBankCodes", fields: [bank_code_id], references: [id])
is_approved Boolean @default(false) timesheet Timesheets @relation("ShiftTimesheet", fields: [timesheet_id], references: [id])
is_remote Boolean @default(false) archive ShiftsArchive[] @relation("ShiftsToArchive")
comment String?
archive ShiftsArchive[] @relation("ShiftsToArchive")
@@unique([timesheet_id, date, start_time], name: "unique_ts_id_date_start_time") @@unique([timesheet_id, date, start_time], name: "unique_ts_id_date_start_time")
@@map("shifts") @@map("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_id Int
shift_id Int archive_at DateTime @default(now())
timesheet_id Int
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)
timesheet_id Int
bank_code_id Int bank_code_id Int
comment String? comment String?
archive_at DateTime @default(now()) shift Shifts @relation("ShiftsToArchive", fields: [shift_id], references: [id])
@@map("shifts_archive") @@map("shifts_archive")
} }
model BankCodes { model BankCodes {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
type String type String
categorie String categorie String
modifier Float modifier Float
bank_code String bank_code String
shifts Shifts[] @relation("ShiftBankCodes")
expenses Expenses[] @relation("ExpenseBankCodes") expenses Expenses[] @relation("ExpenseBankCodes")
leaveRequests LeaveRequests[] @relation("LeaveRequestBankCodes") leaveRequests LeaveRequests[] @relation("LeaveRequestBankCodes")
SchedulePresetShifts SchedulePresetShifts[] @relation("SchedulePresetShiftsBankCodes") SchedulePresetShifts SchedulePresetShifts[] @relation("SchedulePresetShiftsBankCodes")
shifts Shifts[] @relation("ShiftBankCodes")
@@map("bank_codes") @@map("bank_codes")
} }
model Expenses { model Expenses {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
timesheet Timesheets @relation("ExpensesTimesheet", fields: [timesheet_id], references: [id]) timesheet_id Int
timesheet_id Int date DateTime @db.Date
bank_code BankCodes @relation("ExpenseBankCodes", fields: [bank_code_id], references: [id]) amount Decimal? @db.Decimal(12, 2)
bank_code_id Int is_approved Boolean @default(false)
attachment_record Attachments? @relation("ExpenseAttachment", fields: [attachment], references: [id], onDelete: SetNull)
attachment Int?
date DateTime @db.Date
amount Decimal? @db.Decimal(12, 2)
mileage Decimal? @db.Decimal(12, 2)
comment String
supervisor_comment String? supervisor_comment String?
is_approved Boolean @default(false) bank_code_id Int
comment String
archive ExpensesArchive[] @relation("ExpensesToArchive") attachment Int?
mileage Decimal? @db.Decimal(12, 2)
attachment_record Attachments? @relation("ExpenseAttachment", fields: [attachment], references: [id])
bank_code BankCodes @relation("ExpenseBankCodes", fields: [bank_code_id], references: [id])
timesheet Timesheets @relation("ExpensesTimesheet", fields: [timesheet_id], references: [id])
archive ExpensesArchive[] @relation("ExpensesToArchive")
@@unique([timesheet_id, date, amount, mileage], name: "unique_ts_id_date_amount_mileage") @@unique([timesheet_id, date, amount, mileage], name: "unique_ts_id_date_amount_mileage")
@@map("expenses") @@map("expenses")
} }
model ExpensesArchive { model ExpensesArchive {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
expense Expenses @relation("ExpensesToArchive", fields: [expense_id], references: [id]) expense_id Int
expense_id Int
attachment_record Attachments? @relation("ExpenseArchiveAttachment", fields: [attachment], references: [id], onDelete: SetNull)
attachment Int?
timesheet_id Int timesheet_id Int
archived_at DateTime @default(now()) archived_at DateTime @default(now())
bank_code_id Int date DateTime @db.Date
date DateTime @db.Date amount Decimal? @db.Decimal(12, 2)
amount Decimal? @db.Decimal(12, 2)
mileage Decimal? @db.Decimal(12, 2)
comment String?
is_approved Boolean is_approved Boolean
supervisor_comment String? supervisor_comment String?
bank_code_id Int
comment String?
attachment Int?
mileage Decimal? @db.Decimal(12, 2)
attachment_record Attachments? @relation("ExpenseArchiveAttachment", fields: [attachment], references: [id])
expense Expenses @relation("ExpensesToArchive", fields: [expense_id], references: [id])
@@map("expenses_archive") @@map("expenses_archive")
} }
model OAuthSessions { model OAuthSessions {
id String @id @default(cuid()) id String @id @default(cuid())
user Users @relation("UserOAuthSessions", fields: [user_id], references: [id])
user_id String @db.Uuid user_id String @db.Uuid
application String application String
access_token String @unique access_token String @unique
refresh_token String @unique refresh_token String @unique
sid String @unique
access_token_expiry DateTime access_token_expiry DateTime
refresh_token_expiry DateTime? refresh_token_expiry DateTime?
is_revoked Boolean @default(false) is_revoked Boolean @default(false)
scopes Json @default("[]") scopes Json @default("[]")
created_at DateTime @default(now()) created_at DateTime @default(now())
updated_at DateTime? updated_at DateTime?
sid String @unique
user Users @relation("UserOAuthSessions", fields: [user_id], references: [id])
@@map("oauth_sessions") @@map("oauth_sessions")
} }
model Sessions { model Sessions {
id String @id id String @id
sid String @unique sid String @unique
data String data String
expiresAt DateTime expiresAt DateTime
@@map("sessions") @@map("sessions")
} }
model Blobs { model Blobs {
sha256 String @id @db.Char(64) sha256 String @id @db.Char(64)
size Int size Int
mime String mime String
storage_path String storage_path String
refcount Int @default(0) refcount Int @default(0)
created_at DateTime @default(now()) created_at DateTime @default(now())
attachments Attachments[] @relation("AttachmnentBlob")
attachments Attachments[] @relation("AttachmnentBlob")
@@map("blobs") @@map("blobs")
} }
model Attachments { model Attachments {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
blob Blobs @relation("AttachmnentBlob", fields: [sha256], references: [sha256], onUpdate: Cascade) sha256 String @db.Char(64)
sha256 String @db.Char(64) owner_type String
owner_id String
owner_type String //EXPENSES ou éventuellement autre chose comme scan ONU ou photos d'employés, etc status AttachmentStatus @default(ACTIVE)
owner_id String //expense_id, employee_id, etc created_by String
original_name String created_at DateTime @default(now())
status AttachmentStatus @default(ACTIVE) original_name String
retention_policy RetentionPolicy retention_policy RetentionPolicy
created_by String
created_at DateTime @default(now())
expenses Expenses[] @relation("ExpenseAttachment")
expenses_archive ExpensesArchive[] @relation("ExpenseArchiveAttachment")
AttachmentVariants AttachmentVariants[] @relation("attachmentVariantAttachment") AttachmentVariants AttachmentVariants[] @relation("attachmentVariantAttachment")
blob Blobs @relation("AttachmnentBlob", fields: [sha256], references: [sha256])
expenses Expenses[] @relation("ExpenseAttachment")
expenses_archive ExpensesArchive[] @relation("ExpenseArchiveAttachment")
@@index([owner_type, owner_id, created_at]) @@index([owner_type, owner_id, created_at])
@@index([sha256]) @@index([sha256])
@ -336,33 +295,43 @@ model Attachments {
model AttachmentVariants { model AttachmentVariants {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
attachment_id Int attachment_id Int
attachment Attachments @relation("attachmentVariantAttachment", fields: [attachment_id], references: [id], onDelete: Cascade)
variant String variant String
path String
bytes Int bytes Int
width Int? width Int?
height Int? height Int?
created_at DateTime @default(now()) created_at DateTime @default(now())
path String
attachment Attachments @relation("attachmentVariantAttachment", fields: [attachment_id], references: [id], onDelete: Cascade)
@@unique([attachment_id, variant]) @@unique([attachment_id, variant])
@@map("attachment_variants") @@map("attachment_variants")
} }
model Preferences { model Preferences {
id Int @id @default(autoincrement()) user_id String @unique @db.Uuid
user Users @relation("UserPreferences", fields: [user_id], references: [id]) id Int @id @default(autoincrement())
user_id String @unique @db.Uuid display_language String @default("fr-FR")
notifications Boolean @default(true)
is_dark_mode Boolean? @default(false) is_dark_mode Boolean? @default(false)
display_language String @default("fr-FR") //'fr-FR' | 'en-CA';
is_lefty_mode Boolean @default(false)
is_employee_list_grid Boolean @default(true) is_employee_list_grid Boolean @default(true)
is_lefty_mode Boolean @default(false)
is_timesheet_approval_grid Boolean @default(true) is_timesheet_approval_grid Boolean @default(true)
notifications Boolean @default(true)
user Users @relation("UserPreferences", fields: [user_id], references: [id])
@@map("preferences") @@map("preferences")
} }
view PayPeriods {
pay_year Int
pay_period_no BigInt
period_start DateTime @db.Date
period_end DateTime @db.Date
payday DateTime @db.Date
label String
@@map("pay_period")
}
enum AttachmentStatus { enum AttachmentStatus {
ACTIVE ACTIVE
DELETED DELETED
@ -399,14 +368,14 @@ enum Modules {
} }
enum LeaveTypes { enum LeaveTypes {
SICK // maladie ou repos SICK
VACATION // paye VACATION
UNPAID // non-paye UNPAID
BEREAVEMENT // deuil de famille BEREAVEMENT
PARENTAL // maternite/paternite/adoption PARENTAL
LEGAL // obligations legales comme devoir de juree LEGAL
WEDDING // mariage WEDDING
HOLIDAY // férier HOLIDAY
@@map("leave_types") @@map("leave_types")
} }

View File

@ -0,0 +1,79 @@
WITH anchor AS (
SELECT
'2023-12-17' :: date AS anchor_sunday
),
series AS (
SELECT
(gs.gs) :: date AS period_start,
((gs.gs + '13 days' :: INTERVAL)) :: date AS period_end,
((gs.gs + '18 days' :: INTERVAL)) :: date AS payday
FROM
generate_series(
(
(
SELECT
anchor.anchor_sunday
FROM
anchor
)
) :: timestamp WITH time zone,
(((CURRENT_DATE + '1 mon' :: INTERVAL)) :: date) :: timestamp WITH time zone,
'14 days' :: INTERVAL
) gs(gs)
),
numbered AS (
SELECT
series.period_start,
series.period_end,
series.payday,
(
EXTRACT(
year
FROM
series.payday
)
) :: integer AS pay_year,
row_number() OVER (
PARTITION BY (
EXTRACT(
year
FROM
series.payday
)
)
ORDER BY
series.payday
) AS pay_period_no
FROM
series
)
SELECT
pay_year,
pay_period_no,
period_start,
period_end,
payday,
(
(
to_char(
(period_start) :: timestamp WITH time zone,
'YYYY-MM-DD' :: text
) || '->' :: text
) || to_char(
(period_end) :: timestamp WITH time zone,
'YYYY-MM-DD' :: text
)
) AS label
FROM
numbered
WHERE
(
(
payday >= ((CURRENT_DATE - '6 mons' :: INTERVAL)) :: date
)
AND (
payday <= ((CURRENT_DATE + '1 mon' :: INTERVAL)) :: date
)
)
ORDER BY
period_start;

View File

@ -6,7 +6,7 @@ export class SchedulePresetsDto {
@IsInt() id!: number; @IsInt() id!: number;
@IsString() name!: string; @IsString() name!: string;
@IsBoolean() @IsOptional() is_default: boolean; @IsBoolean() @IsOptional() is_default: boolean;
@IsArray() @ArrayMinSize(1) preset_shifts: SchedulePresetShiftsDto[]; @IsArray() @ArrayMinSize(1) shifts: SchedulePresetShiftsDto[];
} }
export class SchedulePresetShiftsDto { export class SchedulePresetShiftsDto {

View File

@ -26,7 +26,7 @@ export class SchedulePresetsCreateService {
}); });
if (existing) return { success: false, error: 'INVALID_SCHEDULE_PRESET' }; if (existing) return { success: false, error: 'INVALID_SCHEDULE_PRESET' };
const normalized_shifts = dto.preset_shifts.map((shift) => ({ const normalized_shifts = dto.shifts.map((shift) => ({
...shift, ...shift,
start: toDateFromHHmm(shift.start_time), start: toDateFromHHmm(shift.start_time),
end: toDateFromHHmm(shift.end_time), end: toDateFromHHmm(shift.end_time),
@ -47,7 +47,7 @@ export class SchedulePresetsCreateService {
} }
//validate bank_code_id/type and map them //validate bank_code_id/type and map them
const bank_code_results = await Promise.all(dto.preset_shifts.map((shift) => const bank_code_results = await Promise.all(dto.shifts.map((shift) =>
this.typeResolver.findBankCodeIDByType(shift.type), this.typeResolver.findBankCodeIDByType(shift.type),
)); ));
for (const result of bank_code_results) { for (const result of bank_code_results) {
@ -68,7 +68,7 @@ export class SchedulePresetsCreateService {
name: dto.name, name: dto.name,
is_default: dto.is_default ?? false, is_default: dto.is_default ?? false,
shifts: { shifts: {
create: dto.preset_shifts.map((shift, index) => { create: dto.shifts.map((shift, index) => {
//validated bank_codes sent as a Result Array to access its data //validated bank_codes sent as a Result Array to access its data
const result = bank_code_results[index] as { success: true, data: number }; const result = bank_code_results[index] as { success: true, data: number };
return { return {

View File

@ -2,7 +2,7 @@ import { Injectable } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service"; import { PrismaService } from "src/prisma/prisma.service";
import { PresetResponse, ShiftResponse } from "src/time-and-attendance/utils/type.utils"; import { SchedulePresetsDto, SchedulePresetShiftsDto } from "../schedule-presets.dto";
import { Result } from "src/common/errors/result-error.factory"; import { Result } from "src/common/errors/result-error.factory";
@ -12,7 +12,7 @@ export class SchedulePresetsGetService {
private readonly prisma: PrismaService, private readonly prisma: PrismaService,
) { } ) { }
async getSchedulePresets(): Promise<Result<PresetResponse[], string>> { async getSchedulePresets(): Promise<Result<SchedulePresetsDto[], string>> {
try { try {
const presets = await this.prisma.schedulePresets.findMany({ const presets = await this.prisma.schedulePresets.findMany({
orderBy: [{ is_default: 'desc' }, { name: 'asc' }], orderBy: [{ is_default: 'desc' }, { name: 'asc' }],
@ -25,11 +25,12 @@ export class SchedulePresetsGetService {
}); });
const hhmm = (date: Date) => date.toISOString().slice(11, 16); const hhmm = (date: Date) => date.toISOString().slice(11, 16);
const response: PresetResponse[] = presets.map((preset) => ({ const response: SchedulePresetsDto[] = presets.map((preset) => ({
id: preset.id, id: preset.id,
name: preset.name, name: preset.name,
is_default: preset.is_default, is_default: preset.is_default,
shifts: preset.shifts.map<ShiftResponse>((shift) => ({ shifts: preset.shifts.map<Omit<SchedulePresetShiftsDto, 'id'>>((shift) => ({
preset_id: shift.preset_id,
week_day: shift.week_day, week_day: shift.week_day,
start_time: hhmm(shift.start_time), start_time: hhmm(shift.start_time),
end_time: hhmm(shift.end_time), end_time: hhmm(shift.end_time),

View File

@ -27,7 +27,7 @@ export class SchedulePresetUpdateService {
}, },
}); });
if (!existing) return { success: false, error: `SCHEDULE_PRESET_NOT_FOUND` }; if (!existing) return { success: false, error: `SCHEDULE_PRESET_NOT_FOUND` };
const normalized_shifts = dto.preset_shifts.map((shift) => ({ const normalized_shifts = dto.shifts.map((shift) => ({
...shift, ...shift,
start: toDateFromHHmm(shift.start_time), start: toDateFromHHmm(shift.start_time),
end: toDateFromHHmm(shift.end_time), end: toDateFromHHmm(shift.end_time),
@ -44,7 +44,7 @@ export class SchedulePresetUpdateService {
if (has_overlap) return { success: false, error: 'SCHEDULE_PRESET_OVERLAP' }; if (has_overlap) return { success: false, error: 'SCHEDULE_PRESET_OVERLAP' };
} }
} }
const bank_code_results = await Promise.all(dto.preset_shifts.map((shift) => const bank_code_results = await Promise.all(dto.shifts.map((shift) =>
this.typeResolver.findBankCodeIDByType(shift.type), this.typeResolver.findBankCodeIDByType(shift.type),
)); ));
for (const result of bank_code_results) { for (const result of bank_code_results) {
@ -69,7 +69,7 @@ export class SchedulePresetUpdateService {
name: dto.name, name: dto.name,
is_default: dto.is_default ?? false, is_default: dto.is_default ?? false,
shifts: { shifts: {
create: dto.preset_shifts.map((shift, index) => { create: dto.shifts.map((shift, index) => {
const result = bank_code_results[index] as { success: true, data: number }; const result = bank_code_results[index] as { success: true, data: number };
return { return {
week_day: shift.week_day, week_day: shift.week_day,

View File

@ -22,20 +22,4 @@ export type NormalizedLeaveRequest = {
dates: Date[]; dates: Date[];
bank_code_id: number; bank_code_id: number;
leave_type: LeaveTypes; leave_type: LeaveTypes;
} }
export type ShiftResponse = {
week_day: string;
start_time: string;
end_time: string;
is_remote: boolean;
type: string;
};
export type PresetResponse = {
id: number;
name: string;
is_default: boolean;
shifts: ShiftResponse[];
}