UNPKG

@accounter/server

Version:
162 lines (149 loc) 5.29 kB
import { GraphQLError } from 'graphql'; import type { Maybe, ResolverFn, ResolversParentTypes, ResolversTypes, } from '../../../../../__generated__/types.js'; import { EMPTY_UUID } from '../../../../../shared/constants.js'; import type { LedgerProto } from '../../../../../shared/types/index.js'; import { AdminContextProvider } from '../../../../admin-context/providers/admin-context.provider.js'; import { calculateDepreciationAmount } from '../../../../reports/helpers/depreciation-report.helper.js'; import { storeInitialGeneratedRecords } from '../../../helpers/ledgrer-storage.helper.js'; import { generateMiscExpensesLedger } from '../../../helpers/misc-expenses-ledger.helper.js'; import { ledgerProtoToRecordsConverter } from '../../../helpers/utils.helper.js'; export const generateLedgerRecordsForDepreciationExpenses: ResolverFn< Maybe<ResolversTypes['GeneratedLedgerRecords']>, ResolversParentTypes['Charge'], GraphQLModules.Context, { insertLedgerRecordsIfNotExists: boolean } > = async (charge, { insertLedgerRecordsIfNotExists }, { injector }) => { try { const { defaultLocalCurrency, depreciation: { accumulatedDepreciationTaxCategoryId, rndDepreciationExpensesTaxCategoryId, gnmDepreciationExpensesTaxCategoryId, marketingDepreciationExpensesTaxCategoryId, }, } = await injector.get(AdminContextProvider).getVerifiedAdminContext(); if (!charge.user_description) { return { __typename: 'CommonError', message: `Depreciation expenses charge must include user description with designated year`, }; } // get revaluation date - search for "yyyy-mm-dd" in description const dateRegex = /\b(\d{4})\b/; const matches = charge.user_description.match(dateRegex); if (!matches?.length) { return { __typename: 'CommonError', message: `Depreciation expenses charge description must include full year`, }; } const stringYear = matches[0]; const year = Number(stringYear); if (Number.isNaN(year) || year < 2000 || year > new Date().getFullYear()) { return { __typename: 'CommonError', message: `Depreciation expenses charge description must include valid year (2000 - current year)`, }; } const { rndDepreciationYearlyAmount, gnmDepreciationYearlyAmount, marketingDepreciationYearlyAmount, totalDepreciationYearlyAmount, } = await calculateDepreciationAmount(injector, year); const ledgerEntries: LedgerProto[] = []; function addLedgerEntry( amount: number, description: string, creditor?: string, debtor?: string, ) { if (amount === 0) { return; } const ledgerEntry: LedgerProto = { id: EMPTY_UUID, invoiceDate: new Date(year, 11, 31), valueDate: new Date(year, 11, 31), currency: defaultLocalCurrency, isCreditorCounterparty: true, creditAccountID1: creditor, debitAccountID1: debtor, localCurrencyCreditAmount1: Math.abs(amount), localCurrencyDebitAmount1: Math.abs(amount), description: `${description} depreciation expenses for ${year}`, ownerId: charge.owner_id, chargeId: charge.id, currencyRate: 1, }; ledgerEntries.push(ledgerEntry); } if (!accumulatedDepreciationTaxCategoryId) { throw new GraphQLError('Accumulated depreciation tax category is not defined'); } if (!rndDepreciationExpensesTaxCategoryId) { throw new GraphQLError('R&D depreciation expenses tax category is not defined'); } if (!gnmDepreciationExpensesTaxCategoryId) { throw new GraphQLError('G&M depreciation expenses tax category is not defined'); } if (!marketingDepreciationExpensesTaxCategoryId) { throw new GraphQLError('Marketing depreciation expenses tax category is not defined'); } addLedgerEntry( rndDepreciationYearlyAmount, 'R&D', undefined, rndDepreciationExpensesTaxCategoryId, ); addLedgerEntry( gnmDepreciationYearlyAmount, 'G&M', undefined, gnmDepreciationExpensesTaxCategoryId, ); addLedgerEntry( marketingDepreciationYearlyAmount, 'Marketing', undefined, marketingDepreciationExpensesTaxCategoryId, ); addLedgerEntry( totalDepreciationYearlyAmount, 'Accumulated', accumulatedDepreciationTaxCategoryId, ); // generate ledger from misc expenses await generateMiscExpensesLedger(charge, injector).then(entries => { entries.map(entry => { entry.ownerId = charge.owner_id; ledgerEntries.push(entry); }); }); if (insertLedgerRecordsIfNotExists) { await storeInitialGeneratedRecords(charge.id, ledgerEntries, injector); } return { records: ledgerProtoToRecordsConverter(ledgerEntries), charge, balance: { isBalanced: true, unbalancedEntities: [], balanceSum: 0, financialEntities: [], }, errors: [], }; } catch (e) { return { __typename: 'CommonError', message: `Failed to generate ledger records for charge ID="${charge.id}"\n${e}`, }; } };