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 { //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 { // 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 { // const where = buildPrismaWhere(filters); // const expenses = await this.prisma.expenses.findMany({ where }) // return expenses; // } // async findOne(id: number): Promise { // 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 { // 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 { // await this.findOne(id); // return this.prisma.expenses.delete({ where: { id } }); // } }