@accounter/server
Version:
Accounter GraphQL server
130 lines • 6.18 kB
JavaScript
import { differenceInDays } from 'date-fns';
import { GraphQLError } from 'graphql';
import { accommodationExpenseDataCollector, BusinessTripError, calculateTotalReportSummaryCategory, carRentalExpensesDataCollector, convertSummaryCategoryDataToRow, flightExpenseDataCollector, onlyUnique, otherExpensesDataCollector, travelAndSubsistenceExpensesDataCollector, } from '../helpers/business-trip-report.helper.js';
import { BusinessTripAttendeesProvider } from '../providers/business-trips-attendees.provider.js';
import { BusinessTripExpensesProvider } from '../providers/business-trips-expenses.provider.js';
import { BusinessTripTaxVariablesProvider } from '../providers/business-trips-tax-variables.provider.js';
export async function businessTripSummary(injector, dbBusinessTrip) {
try {
const attendees = await injector
.get(BusinessTripAttendeesProvider)
.getBusinessTripsAttendeesByBusinessTripIdLoader.load(dbBusinessTrip.id);
if (!attendees?.length) {
return {
rows: [],
errors: ['Attendees are not set'],
};
}
let fromDate;
let toDate;
attendees.map(attendee => {
const { arrival, departure } = attendee;
if (arrival && (!fromDate || arrival < fromDate)) {
fromDate = arrival;
}
if (departure && (!toDate || departure > toDate)) {
toDate = departure;
}
});
if (!fromDate || !toDate) {
return {
rows: [],
errors: ['Business trip dates are not set'],
};
}
const expensesPromise = await injector
.get(BusinessTripExpensesProvider)
.getBusinessTripExtendedExpensesByBusinessTripId(dbBusinessTrip.id);
const taxVariablesPromise = injector
.get(BusinessTripTaxVariablesProvider)
.getTaxVariablesByDateLoader.load(toDate);
const [{ flightExpenses, accommodationsExpenses, travelAndSubsistenceExpenses, otherExpenses, carRentalExpenses, }, taxVariables,] = await Promise.all([expensesPromise, taxVariablesPromise]);
if (!taxVariables) {
return {
rows: [],
errors: ['Tax variables are not set'],
};
}
const summaryData = {};
const attendeesMap = new Map();
attendees.map(attendee => {
const { arrival, departure } = attendee;
let daysCount = 0;
let nightsCount = 0;
if (arrival && departure) {
daysCount = differenceInDays(departure, arrival) + 1;
nightsCount = daysCount - 1;
}
attendeesMap.set(attendee.id, {
name: attendee.name,
arrival,
departure,
daysCount,
nightsCount,
});
});
const errors = [];
const [unAccommodatedDays] = await Promise.all([
accommodationExpenseDataCollector(injector, accommodationsExpenses, summaryData, dbBusinessTrip.destination, taxVariables, attendeesMap).catch(e => {
if (e instanceof BusinessTripError) {
errors.push(e.message);
}
else {
console.error(`Error handling accommodation expenses`, e);
throw new GraphQLError(e?.message ?? `Error handling accommodation expenses`);
}
}),
...flightExpenses.map(flightExpense => flightExpenseDataCollector(injector, flightExpense, summaryData).catch(e => {
if (e instanceof BusinessTripError) {
errors.push(e.message);
}
else {
console.error(`Error handling flight expenses`, e);
throw new GraphQLError(e?.message ?? `Error handling flight expenses`);
}
})),
otherExpensesDataCollector(injector, otherExpenses, summaryData).catch(e => {
if (e instanceof BusinessTripError) {
errors.push(e.message);
}
else {
console.error(`Error handling other expenses`, e);
throw new GraphQLError(e?.message ?? `Error handling other expenses`);
}
}),
carRentalExpensesDataCollector(injector, carRentalExpenses, summaryData, taxVariables, dbBusinessTrip.destination).catch(e => {
if (e instanceof BusinessTripError) {
errors.push(e.message);
}
else {
console.error(`Error handling car rental expenses`, e);
throw new GraphQLError(e?.message ?? `Error handling car rental expenses`);
}
}),
]);
await travelAndSubsistenceExpensesDataCollector(injector, travelAndSubsistenceExpenses, summaryData, taxVariables, {
destinationCode: dbBusinessTrip.destination,
attendees: attendeesMap,
unAccommodatedDays: unAccommodatedDays ?? 0,
}).catch(e => {
if (e instanceof BusinessTripError) {
errors.push(e.message);
}
else {
console.error(`Error handling travel and subsistence expenses`, e);
throw new GraphQLError(e?.message ?? `Error handling travel and subsistence expenses`);
}
});
const totalSumCategory = calculateTotalReportSummaryCategory(summaryData);
summaryData['TOTAL'] = totalSumCategory;
return {
rows: Object.entries(summaryData).map(([category, data]) => convertSummaryCategoryDataToRow(category, data)),
errors: errors.length ? errors.filter(onlyUnique) : undefined,
};
}
catch (e) {
console.error(`Error fetching business trip expenses`, e);
throw new GraphQLError(e?.message ?? `Error fetching business trip expenses`);
}
}
//# sourceMappingURL=business-trip-summary.resolver.js.map