feat(pay-period): add SSE for timesheet-approval when employees update timesheet and a user is on timesheet-approval
This commit is contained in:
parent
646cb58e98
commit
68883b84e7
|
|
@ -35,8 +35,11 @@ export class ExpenseController {
|
||||||
|
|
||||||
@Delete('delete/:expense_id')
|
@Delete('delete/:expense_id')
|
||||||
@ModuleAccessAllowed(ModulesEnum.timesheets)
|
@ModuleAccessAllowed(ModulesEnum.timesheets)
|
||||||
remove(@Param('expense_id') expense_id: number): Promise<Result<number, string>> {
|
remove(
|
||||||
return this.deleteService.deleteExpense(expense_id);
|
@Param('expense_id') expense_id: number,
|
||||||
|
@Access('email') email: string,
|
||||||
|
): Promise<Result<number, string>> {
|
||||||
|
return this.deleteService.deleteExpense(expense_id, email);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { toStringFromDate, weekStartSunday } from "src/common/utils/date-utils";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
import { ExpenseDto } from "src/time-and-attendance/expenses/expense-create.dto";
|
import { ExpenseDto } from "src/time-and-attendance/expenses/expense-create.dto";
|
||||||
import { normalizeAndParseExpenseDto } from "src/time-and-attendance/expenses/expense.utils";
|
import { normalizeAndParseExpenseDto } from "src/time-and-attendance/expenses/expense.utils";
|
||||||
|
import { PayPeriodEventService } from "src/time-and-attendance/pay-period/services/pay-period-event.service";
|
||||||
import { expense_select } from "src/time-and-attendance/utils/selects.utils";
|
import { expense_select } from "src/time-and-attendance/utils/selects.utils";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -14,6 +15,7 @@ export class ExpenseCreateService {
|
||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
private readonly emailResolver: EmailToIdResolver,
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
private readonly typeResolver: BankCodesResolver,
|
private readonly typeResolver: BankCodesResolver,
|
||||||
|
private readonly payPeriodEventService: PayPeriodEventService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
//_________________________________________________________________
|
//_________________________________________________________________
|
||||||
|
|
@ -64,8 +66,15 @@ export class ExpenseCreateService {
|
||||||
attachment: expense.attachment ?? undefined,
|
attachment: expense.attachment ?? undefined,
|
||||||
supervisor_comment: expense.supervisor_comment ?? undefined,
|
supervisor_comment: expense.supervisor_comment ?? undefined,
|
||||||
};
|
};
|
||||||
return { success: true, data: created };
|
|
||||||
|
|
||||||
|
// notify timesheet approval observers of changes
|
||||||
|
this.payPeriodEventService.emit({
|
||||||
|
employee_email: email,
|
||||||
|
event_type: 'expense',
|
||||||
|
action: 'create',
|
||||||
|
});
|
||||||
|
|
||||||
|
return { success: true, data: created };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: 'INVALID_EXPENSE' };
|
return { success: false, error: 'INVALID_EXPENSE' };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,40 @@
|
||||||
import { Injectable } from "@nestjs/common";
|
import { Injectable } from "@nestjs/common";
|
||||||
import { Result } from "src/common/errors/result-error.factory";
|
import { Result } from "src/common/errors/result-error.factory";
|
||||||
|
import { EmailToIdResolver } from "src/common/mappers/email-id.mapper";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
|
import { PayPeriodEventService } from "src/time-and-attendance/pay-period/services/pay-period-event.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ExpenseDeleteService {
|
export class ExpenseDeleteService {
|
||||||
constructor(private readonly prisma: PrismaService) { }
|
constructor(
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
private readonly payPeriodEventService: PayPeriodEventService,
|
||||||
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
|
){}
|
||||||
|
|
||||||
//_________________________________________________________________
|
//_________________________________________________________________
|
||||||
// DELETE
|
// DELETE
|
||||||
//_________________________________________________________________
|
//_________________________________________________________________
|
||||||
async deleteExpense(expense_id: number): Promise<Result<number, string>> {
|
async deleteExpense(expense_id: number, email: string): Promise<Result<number, string>> {
|
||||||
|
// get employee id of employee who made delete request
|
||||||
|
const employee = await this.emailResolver.findIdByEmail(email);
|
||||||
|
|
||||||
|
if (!employee.success) return employee;
|
||||||
|
|
||||||
|
// confirm ownership of expense to employee who made request
|
||||||
|
const expense = await this.prisma.expenses.findUnique({
|
||||||
|
where: { id: expense_id},
|
||||||
|
select: {
|
||||||
|
timesheet: {
|
||||||
|
select: {
|
||||||
|
employee_id: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!expense || expense.timesheet.employee_id !== employee.data) return { success: false, error: 'EXPENSE_NOT_FOUND'};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.prisma.$transaction(async (tx) => {
|
await this.prisma.$transaction(async (tx) => {
|
||||||
const expense = await tx.expenses.findUnique({
|
const expense = await tx.expenses.findUnique({
|
||||||
|
|
@ -21,6 +46,14 @@ export class ExpenseDeleteService {
|
||||||
await tx.expenses.delete({ where: { id: expense.id } });
|
await tx.expenses.delete({ where: { id: expense.id } });
|
||||||
return { success: true, data: expense.id };
|
return { success: true, data: expense.id };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// notify timesheet-approval observers of changes
|
||||||
|
this.payPeriodEventService.emit({
|
||||||
|
employee_email: email,
|
||||||
|
event_type: 'expense',
|
||||||
|
action: 'delete',
|
||||||
|
});
|
||||||
|
|
||||||
return { success: true, data: expense_id };
|
return { success: true, data: expense_id };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: `EXPENSE_NOT_FOUND` };
|
return { success: false, error: `EXPENSE_NOT_FOUND` };
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper";
|
||||||
import { ExpenseDto } from "src/time-and-attendance/expenses/expense-create.dto";
|
import { ExpenseDto } from "src/time-and-attendance/expenses/expense-create.dto";
|
||||||
import { Prisma } from "@prisma/client";
|
import { Prisma } from "@prisma/client";
|
||||||
import { normalizeAndParseExpenseDto } from "src/time-and-attendance/expenses/expense.utils";
|
import { normalizeAndParseExpenseDto } from "src/time-and-attendance/expenses/expense.utils";
|
||||||
|
import { PayPeriodEventService } from "src/time-and-attendance/pay-period/services/pay-period-event.service";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ExpenseUpdateService {
|
export class ExpenseUpdateService {
|
||||||
|
|
@ -15,6 +16,7 @@ export class ExpenseUpdateService {
|
||||||
private readonly prisma: PrismaService,
|
private readonly prisma: PrismaService,
|
||||||
private readonly emailResolver: EmailToIdResolver,
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
private readonly typeResolver: BankCodesResolver,
|
private readonly typeResolver: BankCodesResolver,
|
||||||
|
private readonly payPeriodEventService: PayPeriodEventService,
|
||||||
) { }
|
) { }
|
||||||
//_________________________________________________________________
|
//_________________________________________________________________
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
|
@ -66,6 +68,17 @@ export class ExpenseUpdateService {
|
||||||
attachment: expense.attachment ?? undefined,
|
attachment: expense.attachment ?? undefined,
|
||||||
supervisor_comment: expense.supervisor_comment ?? undefined,
|
supervisor_comment: expense.supervisor_comment ?? undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// notify timesheet-approval observers of changes, but only if it came
|
||||||
|
// from timesheet and not timesheet-approval (no employee_email)
|
||||||
|
if (!employee_email) {
|
||||||
|
this.payPeriodEventService.emit({
|
||||||
|
employee_email: email,
|
||||||
|
event_type: 'expense',
|
||||||
|
action: 'update',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return { success: true, data: updated };
|
return { success: true, data: updated };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return { success: false, error: 'EXPENSE_NOT_FOUND' };
|
return { success: false, error: 'EXPENSE_NOT_FOUND' };
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
export class PayPeriodEvent {
|
export class PayPeriodEvent {
|
||||||
employee_email: string;
|
employee_email: string;
|
||||||
event_type: 'expense' | 'shift';
|
event_type: 'expense' | 'shift' | 'preset';
|
||||||
action: 'create' | 'update' | 'delete';
|
action: 'create' | 'update' | 'delete';
|
||||||
}
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import { ShiftsCreateService } from "src/time-and-attendance/shifts/services/shi
|
||||||
import { VacationService } from "src/time-and-attendance/domains/services/vacation.service";
|
import { VacationService } from "src/time-and-attendance/domains/services/vacation.service";
|
||||||
import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service";
|
import { SickLeaveService } from "src/time-and-attendance/domains/services/sick-leave.service";
|
||||||
import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service";
|
import { BankedHoursService } from "src/time-and-attendance/domains/services/banking-hours.service";
|
||||||
|
import { PayPeriodEventService } from "../pay-period/services/pay-period-event.service";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ import { BankedHoursService } from "src/time-and-attendance/domains/services/ban
|
||||||
VacationService,
|
VacationService,
|
||||||
SickLeaveService,
|
SickLeaveService,
|
||||||
BankedHoursService,
|
BankedHoursService,
|
||||||
|
PayPeriodEventService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
SchedulePresetsGetService,
|
SchedulePresetsGetService,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { timesheet_select } from "src/time-and-attendance/utils/selects.utils";
|
||||||
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
import { ShiftDto } from "src/time-and-attendance/shifts/shift.dto";
|
||||||
import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
|
import { WEEKDAY_MAP } from "src/time-and-attendance/schedule-presets/schedule-presets.dto";
|
||||||
import { $Enums, Prisma, SchedulePresetShifts } from "@prisma/client";
|
import { $Enums, Prisma, SchedulePresetShifts } from "@prisma/client";
|
||||||
|
import { PayPeriodEventService } from "src/time-and-attendance/pay-period/services/pay-period-event.service";
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
@ -20,6 +21,7 @@ export class SchedulePresetsApplyService {
|
||||||
private readonly emailResolver: EmailToIdResolver,
|
private readonly emailResolver: EmailToIdResolver,
|
||||||
private readonly shiftService: ShiftsCreateService,
|
private readonly shiftService: ShiftsCreateService,
|
||||||
private readonly typeResolver: BankCodesResolver,
|
private readonly typeResolver: BankCodesResolver,
|
||||||
|
private readonly payPeriodEventService: PayPeriodEventService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async applyPresetToTimesheet(email: string, timesheet_id: number): Promise<Result<boolean, string>> {
|
async applyPresetToTimesheet(email: string, timesheet_id: number): Promise<Result<boolean, string>> {
|
||||||
|
|
@ -119,6 +121,14 @@ export class SchedulePresetsApplyService {
|
||||||
|
|
||||||
await this.shiftService.createShift(employee_id.data, created_shift.data);
|
await this.shiftService.createShift(employee_id.data, created_shift.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify timesheet-approval observers of changes
|
||||||
|
this.payPeriodEventService.emit({
|
||||||
|
employee_email: email,
|
||||||
|
event_type: 'preset',
|
||||||
|
action: 'create',
|
||||||
|
})
|
||||||
|
|
||||||
return { success: true, data: true };
|
return { success: true, data: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ export class ShiftsUpdateService {
|
||||||
this.payPeriodEventService.emit({
|
this.payPeriodEventService.emit({
|
||||||
employee_email: email,
|
employee_email: email,
|
||||||
event_type: 'shift',
|
event_type: 'shift',
|
||||||
action: 'create'
|
action: 'update'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import { SchedulePresetDeleteService } from "src/time-and-attendance/schedule-pr
|
||||||
import { SchedulePresetUpdateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update.service";
|
import { SchedulePresetUpdateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-update.service";
|
||||||
import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
|
import { SchedulePresetsCreateService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-create.service";
|
||||||
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
|
import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-presets/services/schedule-presets-apply.service";
|
||||||
|
import { PayPeriodEventService } from "./pay-period/services/pay-period-event.service";
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
|
@ -90,6 +91,7 @@ import { SchedulePresetsApplyService } from "src/time-and-attendance/schedule-pr
|
||||||
VacationService,
|
VacationService,
|
||||||
BankedHoursService,
|
BankedHoursService,
|
||||||
PaidTimeOFfBankHoursService,
|
PaidTimeOFfBankHoursService,
|
||||||
|
PayPeriodEventService,
|
||||||
],
|
],
|
||||||
exports: [TimesheetApprovalService],
|
exports: [TimesheetApprovalService],
|
||||||
}) export class TimeAndAttendanceModule { };
|
}) export class TimeAndAttendanceModule { };
|
||||||
Loading…
Reference in New Issue
Block a user