From 7fbcc29b8a95974223acba9f5f73e8ec65288682 Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Mon, 17 Nov 2025 14:54:10 -0500 Subject: [PATCH] fix(expenses): ajusted return values (added type) --- .../controllers/expense.controller.ts | 2 +- .../expenses/dtos/expense-create.dto.ts | 18 +++--- .../services/expense-upsert.service.ts | 55 ++++++++++++------- src/time-and-attendance/utils/type.utils.ts | 1 + 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/time-and-attendance/expenses/controllers/expense.controller.ts b/src/time-and-attendance/expenses/controllers/expense.controller.ts index 88357c1..700fd50 100644 --- a/src/time-and-attendance/expenses/controllers/expense.controller.ts +++ b/src/time-and-attendance/expenses/controllers/expense.controller.ts @@ -19,7 +19,7 @@ export class ExpenseController { } @Patch('update') - update(@Body() dto: ExpenseDto): Promise> { + update(@Body() dto: ExpenseDto): Promise> { return this.upsert_service.updateExpense(dto); } diff --git a/src/time-and-attendance/expenses/dtos/expense-create.dto.ts b/src/time-and-attendance/expenses/dtos/expense-create.dto.ts index 9b028cc..1fa72bd 100644 --- a/src/time-and-attendance/expenses/dtos/expense-create.dto.ts +++ b/src/time-and-attendance/expenses/dtos/expense-create.dto.ts @@ -2,14 +2,14 @@ import { IsBoolean, IsInt, IsOptional, IsString, MaxLength } from "class-validat export class ExpenseDto { @IsInt() @IsOptional() id: number; - @IsInt() bank_code_id!: number; - @IsInt() timesheet_id!: number; + @IsInt() type!: string; + @IsInt() timesheet_id!: number; @IsInt() @IsOptional() attachment?: number; - - @IsString() date!: string; - @IsInt() @IsOptional() amount?: number; - @IsInt() @IsOptional() mileage?: number; - @IsString() @MaxLength(280) comment!: string; - @IsBoolean() is_approved!: boolean; - @IsString() @MaxLength(280) @IsOptional() supervisor_comment?: string + + @IsString() date!: string; + @IsInt() @IsOptional() amount?: number; + @IsInt() @IsOptional() mileage?: number; + @IsString() @MaxLength(280) comment!: string; + @IsBoolean() is_approved!: boolean; + @IsString() @MaxLength(280) @IsOptional() supervisor_comment?: string } \ No newline at end of file diff --git a/src/time-and-attendance/expenses/services/expense-upsert.service.ts b/src/time-and-attendance/expenses/services/expense-upsert.service.ts index 9b66466..ee51f55 100644 --- a/src/time-and-attendance/expenses/services/expense-upsert.service.ts +++ b/src/time-and-attendance/expenses/services/expense-upsert.service.ts @@ -9,6 +9,7 @@ import { Injectable } from "@nestjs/common"; import { Result } from "src/common/errors/result-error.factory"; import { NormalizedExpense } from "src/time-and-attendance/utils/type.utils"; import { weekStartSunday, toStringFromDate, toDateFromString } from "src/common/utils/date-utils"; +import { BankCodesResolver } from "src/common/mappers/bank-type-id.mapper"; @Injectable() @@ -16,6 +17,7 @@ export class ExpenseUpsertService { constructor( private readonly prisma: PrismaService, private readonly emailResolver: EmailToIdResolver, + private readonly typeResolver: BankCodesResolver, ) { } //_________________________________________________________________ @@ -28,10 +30,11 @@ export class ExpenseUpsertService { if (!employee_id.success) return { success: false, error: employee_id.error }; //normalize strings and dates and Parse numbers - const normed_expense = this.normalizeAndParseExpenseDto(dto); + const normed_expense = await this.normalizeAndParseExpenseDto(dto); + if (!normed_expense.success) return { success: false, error: normed_expense.error } //finds the timesheet using expense.date by finding the sunday - const start_date = weekStartSunday(normed_expense.date); + const start_date = weekStartSunday(normed_expense.data.date); const timesheet = await this.prisma.timesheets.findFirst({ where: { start_date, employee_id: employee_id.data }, select: { id: true, employee_id: true }, @@ -41,9 +44,8 @@ export class ExpenseUpsertService { //create a new expense const expense = await this.prisma.expenses.create({ data: { - ...normed_expense, + ...normed_expense.data, timesheet_id: timesheet.id, - bank_code_id: dto.bank_code_id, is_approved: dto.is_approved, }, //return the newly created expense with id @@ -70,17 +72,17 @@ export class ExpenseUpsertService { //_________________________________________________________________ // UPDATE //_________________________________________________________________ - async updateExpense(dto: ExpenseDto): Promise> { + async updateExpense(dto: ExpenseDto): Promise> { try { //normalize string , date format and parse numbers - const normed_expense = this.normalizeAndParseExpenseDto(dto); + const normed_expense = await this.normalizeAndParseExpenseDto(dto); + if (!normed_expense.success) return { success: false, error: normed_expense.error } //checks for modifications const data: ExpenseEntity = { - ...normed_expense, + ...normed_expense.data, id: dto.id, timesheet_id: dto.timesheet_id, - bank_code_id: dto.bank_code_id, is_approved: dto.is_approved, }; if (!data) return { success: false, error: `An error occured during normalization. Expense with id: ${dto.id} is invalid` } @@ -117,14 +119,20 @@ export class ExpenseUpsertService { where: { id: expense_id }, select: { id: true }, }); - if (!expense) return { success: false, error: `An error occured during removal. Expense with id :${expense_id} was not found ` }; + if (!expense) return { + success: false, + error: `An error occured during removal. Expense with id :${expense_id} was not found ` + }; - await tx.expenses.delete({ where: { id: expense_id } }); - return { success: true }; + await tx.expenses.delete({ where: { id: expense.id } }); + return { success: true, data: expense.id }; }); return { success: true, data: expense_id }; } catch (error) { - return { success: false, error: `An error occured during removal. Expense with id :${expense_id} generated an error: ` + error }; + return { + success: false, + error: `An error occured during removal. Expense with id :${expense_id} generated an error: ` + error + }; } } @@ -132,21 +140,30 @@ export class ExpenseUpsertService { // LOCAL HELPERS //_________________________________________________________________ //makes sure that comments are the right length the date is of Date type - private normalizeAndParseExpenseDto(dto: ExpenseDto): NormalizedExpense { + private normalizeAndParseExpenseDto = async (dto: ExpenseDto): Promise> => { const parsed_attachment = this.parseOptionalNumber(dto.attachment, "attachment"); const parsed_mileage = this.parseOptionalNumber(dto.mileage, "mileage"); const parsed_amount = this.parseOptionalNumber(dto.amount, "amount"); + const comment = this.truncate280(dto.comment); const supervisor_comment = dto.supervisor_comment && dto.supervisor_comment.trim() ? this.truncate280(dto.supervisor_comment.trim()) : undefined; + const date = toDateFromString(dto.date); + const type = await this.typeResolver.findBankCodeIDByType(dto.type); + if (!type.success) return { success: false, error: 'Bank-type not found' } + return { - date, - comment, - supervisor_comment, - parsed_amount, - parsed_attachment, - parsed_mileage + success: true, + data: { + date, + comment, + supervisor_comment, + parsed_amount, + parsed_attachment, + parsed_mileage, + bank_code_id: type.data, + } }; } diff --git a/src/time-and-attendance/utils/type.utils.ts b/src/time-and-attendance/utils/type.utils.ts index ff70305..d0c25ea 100644 --- a/src/time-and-attendance/utils/type.utils.ts +++ b/src/time-and-attendance/utils/type.utils.ts @@ -14,6 +14,7 @@ export type NormalizedExpense = { parsed_amount?: number | Prisma.Decimal | null; parsed_mileage?: number | Prisma.Decimal | null; parsed_attachment?: number; + bank_code_id: number; }; export type NormalizedLeaveRequest = {