146 lines
5.4 KiB
TypeScript
146 lines
5.4 KiB
TypeScript
import { Injectable, NotFoundException } from "@nestjs/common";
|
|
import { PrismaService } from "src/prisma/prisma.service";
|
|
import { CreateExpenseDto } from "../dtos/create-expense";
|
|
import { Expenses, ExpensesArchive } from "@prisma/client";
|
|
import { UpdateExpenseDto } from "../dtos/update-expense";
|
|
import { MileageService } from "src/modules/business-logics/services/mileage.service";
|
|
|
|
@Injectable()
|
|
export class ExpensesService {
|
|
constructor(
|
|
private readonly prisma: PrismaService,
|
|
private readonly mileageService: MileageService,
|
|
) {}
|
|
|
|
async create(dto: CreateExpenseDto): Promise<Expenses> {
|
|
const { timesheet_id, bank_code_id, date, amount:rawAmount,
|
|
description, is_approved,supervisor_comment} = dto;
|
|
|
|
|
|
//fetches type and modifier
|
|
const bankCode = await this.prisma.bankCodes.findUnique({
|
|
where: { id: bank_code_id },
|
|
select: { type: true, modifier: true },
|
|
});
|
|
if(!bankCode) {
|
|
throw new NotFoundException(`bank_code #${bank_code_id} not found`)
|
|
}
|
|
|
|
//if mileage -> service, otherwise the ratio is amount:1
|
|
let finalAmount: number;
|
|
if(bankCode.type === 'mileage') {
|
|
finalAmount = await this.mileageService.calculateReimbursement(rawAmount, bank_code_id);
|
|
}else {
|
|
finalAmount = parseFloat( (rawAmount * bankCode.modifier).toFixed(2));
|
|
}
|
|
|
|
return this.prisma.expenses.create({
|
|
data: { timesheet_id, bank_code_id, date, amount: finalAmount, description, is_approved, supervisor_comment},
|
|
include: { timesheet: { include: { employee: { include: { user: true }}}},
|
|
bank_code: true,
|
|
},
|
|
})
|
|
}
|
|
|
|
findAll(): Promise<Expenses[]> {
|
|
return this.prisma.expenses.findMany({
|
|
include: { timesheet: { include: { employee: { include: { user: true } } } } },
|
|
});
|
|
}
|
|
|
|
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,
|
|
description, 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 }),
|
|
...(description !== undefined && { description }),
|
|
...(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 } });
|
|
}
|
|
|
|
|
|
//archivation functions ******************************************************
|
|
|
|
async archiveOld(): Promise<void> {
|
|
//fetches archived timesheet's Ids
|
|
const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({
|
|
select: { timesheet_id: true },
|
|
});
|
|
|
|
const timesheetIds = archivedTimesheets.map(sheet => sheet.timesheet_id);
|
|
if(timesheetIds.length === 0) {
|
|
return;
|
|
}
|
|
|
|
// copy/delete transaction
|
|
await this.prisma.$transaction(async transaction => {
|
|
//fetches expenses to move to archive
|
|
const expensesToArchive = await transaction.expenses.findMany({
|
|
where: { timesheet_id: { in: timesheetIds } },
|
|
});
|
|
if(expensesToArchive.length === 0) {
|
|
return;
|
|
}
|
|
|
|
//copies sent to archive table
|
|
await transaction.expensesArchive.createMany({
|
|
data: expensesToArchive.map(exp => ({
|
|
expense_id: exp.id,
|
|
timesheet_id: exp.timesheet_id,
|
|
bank_code_id: exp.bank_code_id,
|
|
date: exp.date,
|
|
amount: exp.amount,
|
|
attachement: exp.attachement,
|
|
description: exp.description,
|
|
is_approved: exp.is_approved,
|
|
supervisor_comment: exp.supervisor_comment,
|
|
})),
|
|
});
|
|
|
|
//delete from expenses table
|
|
await transaction.expenses.deleteMany({
|
|
where: { id: { in: expensesToArchive.map(exp => exp.id) } },
|
|
})
|
|
|
|
})
|
|
}
|
|
|
|
//fetches all archived timesheets
|
|
async findAllArchived(): Promise<ExpensesArchive[]> {
|
|
return this.prisma.expensesArchive.findMany();
|
|
}
|
|
|
|
//fetches an archived timesheet
|
|
async findOneArchived(id: number): Promise<ExpensesArchive> {
|
|
return this.prisma.expensesArchive.findUniqueOrThrow({ where: { id } });
|
|
}
|
|
} |