@accounter/server
Version:
Accounter GraphQL server
160 lines (138 loc) • 5.28 kB
text/typescript
import type { IGetFinancialEntitiesByIdsResult } from '../../financial-entities/types.js';
import type { IGetLedgerRecordsByDatesResult } from '../../ledger/types.js';
import {
FilteringOptions,
recordsByFinancialEntityIdAndSortCodeValidations,
} from './misc.helper.js';
export type LedgerRecordDecorations = Partial<{
credit_entity_sort_code1: number;
credit_entity_sort_code2: number;
debit_entity_sort_code1: number;
debit_entity_sort_code2: number;
}>;
export type DecoratedLedgerRecord = IGetLedgerRecordsByDatesResult & LedgerRecordDecorations;
export function decorateLedgerRecords(
ledgerRecords: IGetLedgerRecordsByDatesResult[],
financialEntitiesDict: Map<string, IGetFinancialEntitiesByIdsResult>,
): DecoratedLedgerRecord[] {
return ledgerRecords.map(record => {
const sortCodes: LedgerRecordDecorations = {};
if (record.credit_entity1) {
const sortCode = financialEntitiesDict.get(record.credit_entity1)?.sort_code;
if (!sortCode) {
console.error(`No sort code for financial entity ${record.credit_entity1}`);
}
sortCodes.credit_entity_sort_code1 = sortCode ?? undefined;
}
if (record.credit_entity2) {
const sortCode = financialEntitiesDict.get(record.credit_entity2)?.sort_code;
if (!sortCode) {
console.error(`No sort code for financial entity ${record.credit_entity2}`);
}
sortCodes.credit_entity_sort_code2 = sortCode ?? undefined;
}
if (record.debit_entity1) {
const sortCode = financialEntitiesDict.get(record.debit_entity1)?.sort_code;
if (!sortCode) {
console.error(`No sort code for financial entity ${record.debit_entity1}`);
}
sortCodes.debit_entity_sort_code1 = sortCode ?? undefined;
}
if (record.debit_entity2) {
const sortCode = financialEntitiesDict.get(record.debit_entity2)?.sort_code;
if (!sortCode) {
console.error(`No sort code for financial entity ${record.debit_entity2}`);
}
sortCodes.debit_entity_sort_code2 = sortCode ?? undefined;
}
return {
...record,
...sortCodes,
};
});
}
export function getProfitLossReportAmounts(decoratedLedgerRecords: DecoratedLedgerRecord[]) {
const revenueFilter: FilteringOptions = {
rule: (_, sortCode) => [800, 810].includes(sortCode),
};
const costOfSalesFilter: FilteringOptions = {
rule: (_, sortCode) => [910, 911, 912, 915].includes(sortCode),
};
const researchAndDevelopmentExpensesFilter: FilteringOptions = {
rule: (_, sortCode) => [920, 921, 922, 923, 924, 925, 930, 931].includes(sortCode),
};
const marketingExpensesFilter: FilteringOptions = {
rule: (_, sortCode) => [935, 936].includes(sortCode),
};
const managementAndGeneralExpensesFilter: FilteringOptions = {
rule: (_, sortCode) => [940, 941, 942, 943, 944, 945, 946, 947, 948].includes(sortCode),
};
const financialExpensesFilter: FilteringOptions = {
rule: (_, sortCode) => [990, 991, 992].includes(sortCode),
};
const otherIncomeFilter: FilteringOptions = {
rule: (_, sortCode) => sortCode === 995,
};
const [
revenue,
costOfSales,
researchAndDevelopmentExpenses,
marketingExpenses,
managementAndGeneralExpenses,
financialExpenses,
otherIncome,
] = recordsByFinancialEntityIdAndSortCodeValidations(decoratedLedgerRecords, [
revenueFilter,
costOfSalesFilter,
researchAndDevelopmentExpensesFilter,
marketingExpensesFilter,
managementAndGeneralExpensesFilter,
financialExpensesFilter,
otherIncomeFilter,
]);
const { amount: revenueAmount, records: revenueRecords } = revenue;
const { amount: costOfSalesAmount, records: costOfSalesRecords } = costOfSales;
const grossProfitAmount = revenueAmount + costOfSalesAmount;
const {
amount: researchAndDevelopmentExpensesAmount,
records: researchAndDevelopmentExpensesRecords,
} = researchAndDevelopmentExpenses;
const { amount: marketingExpensesAmount, records: marketingExpensesRecords } = marketingExpenses;
const {
amount: managementAndGeneralExpensesAmount,
records: managementAndGeneralExpensesRecords,
} = managementAndGeneralExpenses;
const operatingProfitAmount =
grossProfitAmount +
researchAndDevelopmentExpensesAmount +
marketingExpensesAmount +
managementAndGeneralExpensesAmount;
const { amount: financialExpensesAmount, records: financialExpensesRecords } = financialExpenses;
const { amount: otherIncomeAmount, records: otherIncomeRecords } = otherIncome;
const profitBeforeTaxAmount = operatingProfitAmount + financialExpensesAmount + otherIncomeAmount;
const profitBeforeTaxRecords = [
...revenueRecords,
...costOfSalesRecords,
...researchAndDevelopmentExpensesRecords,
...marketingExpensesRecords,
...managementAndGeneralExpensesRecords,
...financialExpensesRecords,
...otherIncomeRecords,
];
const profitBeforeTax = {
amount: profitBeforeTaxAmount,
records: profitBeforeTaxRecords,
};
return {
revenue,
costOfSales,
grossProfitAmount,
researchAndDevelopmentExpenses,
marketingExpenses,
managementAndGeneralExpenses,
operatingProfitAmount,
financialExpenses,
otherIncome,
profitBeforeTax,
};
}