refactor(shifts): added is_remote to track work from home shifts

This commit is contained in:
Matthieu Haineault 2025-09-08 15:25:09 -04:00
parent dac53c6780
commit 954411d995
10 changed files with 17 additions and 64 deletions

View File

@ -182,6 +182,7 @@ model Shifts {
start_time DateTime @db.Time(0) start_time DateTime @db.Time(0)
end_time DateTime @db.Time(0) end_time DateTime @db.Time(0)
is_approved Boolean @default(false) is_approved Boolean @default(false)
is_remote Boolean @default(false)
archive ShiftsArchive[] @relation("ShiftsToArchive") archive ShiftsArchive[] @relation("ShiftsToArchive")

View File

@ -41,4 +41,6 @@ export class EmployeePeriodOverviewDto {
description: 'Tous les timesheets de la période sont approuvés pour cet employé', description: 'Tous les timesheets de la période sont approuvés pour cet employé',
}) })
is_approved: boolean; is_approved: boolean;
is_remote: boolean;
} }

View File

@ -68,38 +68,4 @@ export class PayPeriodsCommandService {
}); });
return {updated}; return {updated};
} }
//function to approve a single pay-period of a single employee (deprecated)
// async approvalPayPeriod(pay_year: number , period_no: number): Promise<void> {
// const period = await this.prisma.payPeriods.findFirst({
// where: { pay_year, pay_period_no: period_no},
// });
// if (!period) throw new NotFoundException(`PayPeriod #${pay_year}-${period_no} not found`);
// //fetches timesheet of selected period if the timesheet has atleast 1 shift or 1 expense
// const timesheet_ist = await this.prisma.timesheets.findMany({
// where: {
// OR: [
// { shift: {some: { date: { gte: period.period_start,
// lte: period.period_end,
// },
// }},
// },
// { expense: { some: { date: { gte: period.period_start,
// lte: period.period_end,
// },
// }},
// },
// ],
// },
// select: { id: true },
// });
// //approval of both timesheet (cascading to the approval of related shifts and expenses)
// await this.prisma.$transaction(async (transaction)=> {
// for(const {id} of timesheet_ist) {
// await this.timesheets_approval.updateApprovalWithTransaction(transaction,id, true);
// }
// })
// }
} }

View File

@ -151,6 +151,7 @@ export class PayPeriodsQueryService {
select: { select: {
start_time: true, start_time: true,
end_time: true, end_time: true,
is_remote: true,
timesheet: { select: { timesheet: { select: {
is_approved: true, is_approved: true,
employee: { select: { employee: { select: {
@ -205,6 +206,7 @@ export class PayPeriodsQueryService {
expenses: 0, expenses: 0,
mileage: 0, mileage: 0,
is_approved: true, is_approved: true,
is_remote: true,
}); });
} }
} }
@ -221,6 +223,7 @@ export class PayPeriodsQueryService {
expenses: 0, expenses: 0,
mileage: 0, mileage: 0,
is_approved: true, is_approved: true,
is_remote: true,
}); });
} }
return by_employee.get(id)!; return by_employee.get(id)!;

View File

@ -108,7 +108,7 @@ export class ShiftsController {
r.total_overtime_hrs.toFixed(2), r.total_overtime_hrs.toFixed(2),
r.total_expenses.toFixed(2), r.total_expenses.toFixed(2),
r.total_mileage.toFixed(2), r.total_mileage.toFixed(2),
r.is_validated, r.is_approved,
].join(','); ].join(',');
}).join('\n'); }).join('\n');

View File

@ -18,7 +18,7 @@ export interface OverviewRow {
total_overtime_hrs: number; total_overtime_hrs: number;
total_expenses: number; total_expenses: number;
total_mileage: number; total_mileage: number;
is_validated: boolean; is_approved: boolean;
} }
@Injectable() @Injectable()
@ -168,7 +168,7 @@ export class ShiftsQueryService {
total_overtime_hrs: 0, total_overtime_hrs: 0,
total_expenses: 0, total_expenses: 0,
total_mileage: 0, total_mileage: 0,
is_validated: false, is_approved: false,
}; };
} }
const hours = computeHours(shift.start_time, shift.end_time); const hours = computeHours(shift.start_time, shift.end_time);
@ -200,7 +200,7 @@ export class ShiftsQueryService {
total_overtime_hrs: 0, total_overtime_hrs: 0,
total_expenses: 0, total_expenses: 0,
total_mileage: 0, total_mileage: 0,
is_validated: false, is_approved: false,
}; };
} }
const amount = Number(exp.amount); const amount = Number(exp.amount);

View File

@ -14,6 +14,7 @@ export class ShiftsDto {
end_time: string; end_time: string;
description: string; description: string;
is_approved: boolean; is_approved: boolean;
is_remote: boolean;
} }
export class ExpensesDto { export class ExpensesDto {

View File

@ -2,6 +2,7 @@ export class ShiftDto {
start: string; start: string;
end : string; end : string;
is_approved: boolean; is_approved: boolean;
is_remote: boolean;
} }
export class ExpenseDto { export class ExpenseDto {

View File

@ -119,6 +119,7 @@ export class TimesheetsCommandService extends BaseApprovalService<Timesheets>{
end_time: this.parseHHmm(shift.end_time), end_time: this.parseHHmm(shift.end_time),
description: shift.description ?? null, description: shift.description ?? null,
is_approved: false, is_approved: false,
is_remote: false,
}, },
}); });
} }

View File

@ -18,17 +18,6 @@ export class TimesheetsQueryService {
private readonly overtime: OvertimeService, private readonly overtime: OvertimeService,
) {} ) {}
// 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 }
// },
// },
// });
// }
async findAll(year: number, period_no: number, email: string): Promise<TimesheetPeriodDto> { async findAll(year: number, period_no: number, email: string): Promise<TimesheetPeriodDto> {
//finds the employee //finds the employee
const employee = await this.prisma.employees.findFirst({ const employee = await this.prisma.employees.findFirst({
@ -57,6 +46,7 @@ export class TimesheetsQueryService {
start_time: true, start_time: true,
end_time: true, end_time: true,
is_approved: true, is_approved: true,
is_remote: true,
bank_code: { select: { type: true } }, bank_code: { select: { type: true } },
}, },
orderBy:[ { date:'asc'}, { start_time: 'asc'} ], orderBy:[ { date:'asc'}, { start_time: 'asc'} ],
@ -87,6 +77,7 @@ export class TimesheetsQueryService {
end_time: shift.end_time, end_time: shift.end_time,
type: String(shift.bank_code?.type ?? '').toUpperCase(), type: String(shift.bank_code?.type ?? '').toUpperCase(),
is_approved: shift.is_approved ?? true, is_approved: shift.is_approved ?? true,
is_remote: shift.is_remote ?? true,
})); }));
const expenses: ExpenseRow[] = raw_expenses.map(expense => ({ const expenses: ExpenseRow[] = raw_expenses.map(expense => ({
@ -153,6 +144,7 @@ export class TimesheetsQueryService {
if(!timesheet) { if(!timesheet) {
return { return {
is_approved: false, is_approved: false,
is_remote: false,
start_day, start_day,
end_day, end_day,
label, label,
@ -172,6 +164,7 @@ export class TimesheetsQueryService {
end_time: to_HH_mm(sft.end_time), end_time: to_HH_mm(sft.end_time),
description: sft.description ?? '', description: sft.description ?? '',
is_approved: sft.is_approved ?? false, is_approved: sft.is_approved ?? false,
is_remote: sft.is_remote ?? false,
})); }));
//maps all expenses of selected timsheet //maps all expenses of selected timsheet
@ -223,21 +216,6 @@ export class TimesheetsQueryService {
return { ...timesheet, shift: detailedShifts, weeklyOvertimeHours }; return { ...timesheet, shift: detailedShifts, weeklyOvertimeHours };
} }
//deprecated
// 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> { async remove(id: number): Promise<Timesheets> {
await this.findOne(id); await this.findOne(id);
return this.prisma.timesheets.delete({ where: { id } }); return this.prisma.timesheets.delete({ where: { id } });