targo-backend/src/modules/expenses/services/expenses-query.service.ts
2025-10-10 13:29:26 -04:00

174 lines
6.6 KiB
TypeScript

import { Injectable, NotFoundException } from "@nestjs/common";
import { PrismaService } from "src/prisma/prisma.service";
import { DayExpensesDto as ExpenseListResponseDto, ExpenseDto } from "src/modules/timesheets/dtos/timesheet-period.dto";
import { round2, toUTCDateOnly } from "src/modules/timesheets/utils-helpers-others/timesheet.helpers";
import { EXPENSE_TYPES } from "src/modules/timesheets/utils-helpers-others/timesheet.types";
import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils";
@Injectable()
export class ExpensesQueryService {
constructor(
private readonly prisma: PrismaService,
private readonly employeeRepo: EmailToIdResolver,
) {}
//fetchs all expenses for a selected employee using email, pay-period-year and number
async findExpenseListByPayPeriodAndEmail(
email: string,
year: number,
period_no: number
): Promise<ExpenseListResponseDto> {
//fetch employe_id using email
const employee_id = await this.employeeRepo.findIdByEmail(email);
if(!employee_id) throw new NotFoundException(`Employee with email: ${email} not found`);
//fetch pay-period using year and period_no
const pay_period = await this.prisma.payPeriods.findFirst({
where: {
pay_year: year,
pay_period_no: period_no
},
select: { period_start: true, period_end: true },
});
if(!pay_period) throw new NotFoundException(`Pay period ${year}- ${period_no} not found`);
const start = toUTCDateOnly(pay_period.period_start);
const end = toUTCDateOnly(pay_period.period_end);
//sets rows data
const rows = await this.prisma.expenses.findMany({
where: {
date: { gte: start, lte: end },
timesheet: { is: { employee_id } },
},
orderBy: { date: 'asc'},
select: {
amount: true,
mileage: true,
comment: true,
is_approved: true,
supervisor_comment: true,
bank_code: {select: { type: true } },
},
});
//declare return values
const expenses: ExpenseDto[] = [];
let total_amount = 0;
let total_mileage = 0;
//set rows
for(const row of rows) {
const type = (row.bank_code?.type ?? '').toUpperCase();
const amount = round2(Number(row.amount ?? 0));
const mileage = round2(Number(row.mileage ?? 0));
if(type === EXPENSE_TYPES.MILEAGE) {
total_mileage += mileage;
} else {
total_amount += amount;
}
//fills rows array
expenses.push({
type,
amount,
mileage,
comment: row.comment ?? '',
is_approved: row.is_approved ?? false,
supervisor_comment: row.supervisor_comment ?? '',
});
}
return {
expenses,
total_expense: round2(total_amount),
total_mileage: round2(total_mileage),
};
}
//_____________________________________________________________________________________________
// Deprecated or unused methods
//_____________________________________________________________________________________________
// async create(dto: CreateExpenseDto): Promise<Expenses> {
// const { timesheet_id, bank_code_id, date, amount:rawAmount,
// comment, is_approved,supervisor_comment} = dto;
// //fetches type and modifier
// const bank_code = await this.prisma.bankCodes.findUnique({
// where: { id: bank_code_id },
// select: { type: true, modifier: true },
// });
// if(!bank_code) throw new NotFoundException(`bank_code #${bank_code_id} not found`);
// //if mileage -> service, otherwise the ratio is amount:1
// let final_amount: number;
// if(bank_code.type === 'mileage') {
// final_amount = await this.mileageService.calculateReimbursement(rawAmount, bank_code_id);
// }else {
// final_amount = parseFloat( (rawAmount * bank_code.modifier).toFixed(2));
// }
// return this.prisma.expenses.create({
// data: {
// timesheet_id,
// bank_code_id,
// date,
// amount: final_amount,
// comment,
// is_approved,
// supervisor_comment
// },
// include: { timesheet: { include: { employee: { include: { user: true }}}},
// bank_code: true,
// },
// })
// }
// async findAll(filters: SearchExpensesDto): Promise<Expenses[]> {
// const where = buildPrismaWhere(filters);
// const expenses = await this.prisma.expenses.findMany({ where })
// return expenses;
// }
// async findOne(id: number): Promise<Expenses> {
// const expense = await this.prisma.expenses.findUnique({
// where: { id },
// include: { timesheet: { include: { employee: { include: { user:true } } } },
// bank_code: true,
// },
// });
// if (!expense) {
// throw new NotFoundException(`Expense #${id} not found`);
// }
// return expense;
// }
// async update(id: number, dto: UpdateExpenseDto): Promise<Expenses> {
// await this.findOne(id);
// const { timesheet_id, bank_code_id, date, amount,
// comment, is_approved, supervisor_comment} = dto;
// return this.prisma.expenses.update({
// where: { id },
// data: {
// ...(timesheet_id !== undefined && { timesheet_id}),
// ...(bank_code_id !== undefined && { bank_code_id }),
// ...(date !== undefined && { date }),
// ...(amount !== undefined && { amount }),
// ...(comment !== undefined && { comment }),
// ...(is_approved !== undefined && { is_approved }),
// ...(supervisor_comment !== undefined && { supervisor_comment }),
// },
// include: { timesheet: { include: { employee: { include: { user: true } } } },
// bank_code: true,
// },
// });
// }
// async remove(id: number): Promise<Expenses> {
// await this.findOne(id);
// return this.prisma.expenses.delete({ where: { id } });
// }
}