targo-backend/src/~misc_deprecated-files/expenses-command.service.ts
2025-10-27 11:47:38 -04:00

249 lines
9.7 KiB
TypeScript

// import { BaseApprovalService } from "src/common/shared/base-approval.service";
// import { Expenses, Prisma } from "@prisma/client";
// import { PrismaService } from "src/prisma/prisma.service";
// import { UpsertExpenseDto } from "../dtos/upsert-expense.dto";
// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils";
// import { ExpenseResponse, UpsertAction } from "../types and interfaces/expenses.types.interfaces";
// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils";
// import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-timesheet.utils";
// import {
// BadRequestException,
// Injectable,
// NotFoundException
// } from "@nestjs/common";
// import {
// assertAndTrimComment,
// computeAmountDecimal,
// computeMileageAmount,
// mapDbExpenseToDayResponse,
// normalizeType,
// parseAttachmentId
// } from "../utils/expenses.utils";
// @Injectable()
// export class ExpensesCommandService extends BaseApprovalService<Expenses> {
// constructor(
// prisma: PrismaService,
// private readonly bankCodesResolver: BankCodesResolver,
// private readonly timesheetsResolver: EmployeeTimesheetResolver,
// private readonly emailResolver: EmailToIdResolver,
// ) { super(prisma); }
// //_____________________________________________________________________________________________
// // APPROVAL TX-DELEGATE METHODS
// //_____________________________________________________________________________________________
// protected get delegate() {
// return this.prisma.expenses;
// }
// protected delegateFor(transaction: Prisma.TransactionClient){
// return transaction.expenses;
// }
// async updateApproval(id: number, isApproved: boolean): Promise<Expenses> {
// return this.prisma.$transaction((transaction) =>
// this.updateApprovalWithTransaction(transaction, id, isApproved),
// );
// }
// //_____________________________________________________________________________________________
// // MASTER CRUD FUNCTION
// //_____________________________________________________________________________________________
// readonly upsertExpensesByDate = async (email: string, date: string, dto: UpsertExpenseDto,
// ): Promise<{ action:UpsertAction; day: ExpenseResponse[] }> => {
// //validates if there is an existing expense, at least 1 old or new
// const { old_expense, new_expense } = dto ?? {};
// if(!old_expense && !new_expense) throw new BadRequestException('At least one expense must be provided');
// //validate date format
// const date_only = toDateOnly(date);
// if(Number.isNaN(date_only.getTime())) throw new BadRequestException('Invalid date format (expected: YYYY-MM-DD)');
// //resolve employee_id by email
// const employee_id = await this.emailResolver.findIdByEmail(email);
// //make sure a timesheet existes
// const timesheet_id = await this.timesheetsResolver.findTimesheetIdByEmail(email, date_only);
// if(!timesheet_id) throw new NotFoundException(`no timesheet found for employee #${employee_id}`)
// const {id} = timesheet_id;
// return this.prisma.$transaction(async (tx) => {
// const loadDay = async (): Promise<ExpenseResponse[]> => {
// const rows = await tx.expenses.findMany({
// where: {
// timesheet_id: id,
// date: date_only,
// },
// include: {
// bank_code: {
// select: {
// type: true,
// },
// },
// },
// orderBy: [{ date: 'asc' }, { id: 'asc' }],
// });
// return rows.map((r) =>
// mapDbExpenseToDayResponse({
// date: r.date,
// amount: r.amount ?? 0,
// mileage: r.mileage ?? 0,
// comment: r.comment,
// is_approved: r.is_approved,
// bank_code: r.bank_code,
// }));
// };
// const normalizePayload = async (payload: {
// type: string;
// amount?: number;
// mileage?: number;
// comment: string;
// attachment?: string | number;
// }): Promise<{
// type: string;
// bank_code_id: number;
// amount: Prisma.Decimal;
// mileage: number | null;
// comment: string;
// attachment: number | null;
// }> => {
// const type = normalizeType(payload.type);
// const comment = assertAndTrimComment(payload.comment);
// const attachment = parseAttachmentId(payload.attachment);
// const { id: bank_code_id, modifier } = await this.bankCodesResolver.findByType(type);
// let amount = computeAmountDecimal(type, payload, modifier);
// let mileage: number | null = null;
// if (type === 'MILEAGE') {
// mileage = Number(payload.mileage ?? 0);
// if (!(mileage > 0)) {
// throw new BadRequestException('Mileage required and must be > 0 for type MILEAGE');
// }
// const amountNumber = computeMileageAmount(mileage, modifier);
// amount = new Prisma.Decimal(amountNumber);
// } else {
// if (!(typeof payload.amount === 'number' && payload.amount >= 0)) {
// throw new BadRequestException('Amount required for non-MILEAGE expense');
// }
// amount = new Prisma.Decimal(payload.amount);
// }
// if (attachment !== null) {
// const attachment_row = await tx.attachments.findUnique({
// where: { id: attachment },
// select: { status: true },
// });
// if (!attachment_row || attachment_row.status !== 'ACTIVE') {
// throw new BadRequestException('Attachment not found or inactive');
// }
// }
// return {
// type,
// bank_code_id,
// amount,
// mileage,
// comment,
// attachment
// };
// };
// const findExactOld = async (norm: {
// bank_code_id: number;
// amount: Prisma.Decimal;
// mileage: number | null;
// comment: string;
// attachment: number | null;
// }) => {
// return tx.expenses.findFirst({
// where: {
// timesheet_id: id,
// date: date_only,
// bank_code_id: norm.bank_code_id,
// amount: norm.amount,
// comment: norm.comment,
// attachment: norm.attachment,
// ...(norm.mileage !== null ? { mileage: norm.mileage } : { mileage: null }),
// },
// select: { id: true },
// });
// };
// let action : UpsertAction;
// //_____________________________________________________________________________________________
// // DELETE
// //_____________________________________________________________________________________________
// if(old_expense && !new_expense) {
// const old_norm = await normalizePayload(old_expense);
// const existing = await findExactOld(old_norm);
// if(!existing) {
// throw new NotFoundException({
// error_code: 'EXPENSE_STALE',
// message: 'The expense was modified or deleted by someone else',
// });
// }
// await tx.expenses.delete({where: { id: existing.id } });
// action = 'delete';
// }
// //_____________________________________________________________________________________________
// // CREATE
// //_____________________________________________________________________________________________
// else if (!old_expense && new_expense) {
// const new_exp = await normalizePayload(new_expense);
// await tx.expenses.create({
// data: {
// timesheet_id: id,
// date: date_only,
// bank_code_id: new_exp.bank_code_id,
// amount: new_exp.amount,
// mileage: new_exp.mileage,
// comment: new_exp.comment,
// attachment: new_exp.attachment,
// is_approved: false,
// },
// });
// action = 'create';
// }
// //_____________________________________________________________________________________________
// // UPDATE
// //_____________________________________________________________________________________________
// else if(old_expense && new_expense) {
// const old_norm = await normalizePayload(old_expense);
// const existing = await findExactOld(old_norm);
// if(!existing) {
// throw new NotFoundException({
// error_code: 'EXPENSE_STALE',
// message: 'The expense was modified or deleted by someone else',
// });
// }
// const new_exp = await normalizePayload(new_expense);
// await tx.expenses.update({
// where: { id: existing.id },
// data: {
// bank_code_id: new_exp.bank_code_id,
// amount: new_exp.amount,
// mileage: new_exp.mileage,
// comment: new_exp.comment,
// attachment: new_exp.attachment,
// },
// });
// action = 'update';
// }
// else {
// throw new BadRequestException('Invalid upsert combination');
// }
// const day = await loadDay();
// return { action, day };
// });
// }
// }