@accounter/server
Version:
Accounter GraphQL server
153 lines • 7.4 kB
JavaScript
import { GraphQLError } from 'graphql';
import { errorSimplifier } from '../../../shared/errors.js';
import { formatFinancialAmount } from '../../../shared/helpers/index.js';
import { TransactionsProvider } from '../../transactions/providers/transactions.provider.js';
import { BankDepositChargesProvider } from '../providers/bank-deposit-charges.provider.js';
import { BankDepositsProvider } from '../providers/bank-deposits.provider.js';
export const bankDepositChargesResolvers = {
Query: {
depositByCharge: async (_, { chargeId }, { injector }) => {
try {
return await injector
.get(BankDepositChargesProvider)
.getBankDepositByChargeIdLoader.load(chargeId);
}
catch (e) {
throw errorSimplifier('Error fetching deposit by charge', e);
}
},
relevantDepositsForCharge: async (_, { chargeId }, { injector }) => {
try {
const transactions = await injector
.get(TransactionsProvider)
.transactionsByChargeIDLoader.load(chargeId);
if (transactions.length === 0) {
return { id: chargeId, deposits: [], error: null };
}
const currencies = new Set(transactions.map(t => t.currency).filter(Boolean));
const accountIds = new Set(transactions.map(t => t.account_id).filter(Boolean));
if (currencies.size > 1) {
return {
id: chargeId,
deposits: [],
error: `Charge has transactions in multiple currencies (${[...currencies].join(', ')})`,
};
}
if (accountIds.size > 1) {
return {
id: chargeId,
deposits: [],
error: 'Charge has transactions from multiple accounts',
};
}
const chargeCurrency = currencies.size === 1 ? [...currencies][0] : null;
const chargeAccountId = accountIds.size === 1 ? [...accountIds][0] : null;
const allOpen = await injector.get(BankDepositsProvider).getAllOpenBankDeposits();
const relevant = allOpen.filter(deposit => {
const currencyMatch = deposit.currency == null ||
chargeCurrency == null ||
deposit.currency === chargeCurrency;
const accountMatch = deposit.account_id == null ||
chargeAccountId == null ||
deposit.account_id === chargeAccountId;
return currencyMatch && accountMatch;
});
return { id: chargeId, deposits: relevant, error: null };
}
catch (e) {
throw errorSimplifier('Error fetching relevant deposits for charge', e);
}
},
},
Mutation: {
assignChargeToDeposit: async (_, { chargeId, depositId }, { injector }) => {
try {
await injector.get(BankDepositChargesProvider).assignChargeToDeposit(chargeId, depositId);
return injector
.get(BankDepositChargesProvider)
.getBankDepositByChargeIdLoader.load(chargeId)
.then(deposit => {
if (!deposit) {
throw new GraphQLError('Deposit not found for charge after assignment');
}
return deposit;
});
}
catch (e) {
throw errorSimplifier('Error assigning transaction to deposit', e);
}
},
createDepositFromCharge: async (_, { chargeId, name }, { injector }) => {
try {
const transactions = await injector
.get(TransactionsProvider)
.transactionsByChargeIDLoader.load(chargeId);
if (transactions.length === 0) {
throw new GraphQLError('Deposit creation from charge requires charges that have at least one transaction');
}
const currencies = new Set();
const accountIds = new Set();
let openDate = null;
transactions.map(t => {
currencies.add(t.currency);
if (t.account_id) {
accountIds.add(t.account_id);
}
// Derive open_date from the earliest debit_date, falling back to event_date
const transactionDate = t.debit_date ?? t.event_date;
if (transactionDate && (!openDate || transactionDate < openDate)) {
openDate = transactionDate;
}
});
// Validate single currency and single account across all transactions
if (currencies.size > 1) {
throw new GraphQLError(`Cannot create deposit: charge has transactions in multiple currencies (${[...currencies].join(', ')})`);
}
if (accountIds.size > 1) {
throw new GraphQLError(`Cannot create deposit: charge has transactions from multiple accounts`);
}
const currency = [...currencies][0];
const accountId = [...accountIds][0] ?? null;
const deposit = await injector.get(BankDepositsProvider).insertBankDeposit({
name,
currency,
accountId,
openDate,
closeDate: null,
});
if (!deposit) {
throw new GraphQLError('Failed to create bank deposit');
}
await injector
.get(BankDepositChargesProvider)
.upsertBankDepositCharge({ chargeId, depositId: deposit.id });
injector.get(BankDepositChargesProvider).getBankDepositByChargeIdLoader.clear(chargeId);
return deposit;
}
catch (e) {
throw errorSimplifier('Error creating deposit from charge', e);
}
},
},
BankDeposit: {
metadata: async (deposit, _, { injector }) => {
try {
return await injector
.get(BankDepositChargesProvider)
.getBankDepositMetadataLoader.load(deposit.id);
}
catch (e) {
throw errorSimplifier(`Error fetching metadata for deposit ${deposit.name}`, e);
}
},
},
BankDepositMetadata: {
id: metadata => metadata.id,
currentBalance: metadata => formatFinancialAmount(metadata.currentBalance),
totalInterest: metadata => formatFinancialAmount(metadata.totalInterest),
totalDeposit: metadata => formatFinancialAmount(metadata.totalDeposit),
potentialCloseDate: metadata => Math.abs(metadata.currentBalance) >= 0.005 ? metadata.potentialCloseDate : null,
transactions: metadata => metadata.transactionIds,
},
};
//# sourceMappingURL=bank-deposit-charges.resolver.js.map