UNPKG

@accounter/server

Version:
278 lines (266 loc) • 11.7 kB
import { GraphQLError } from 'graphql'; import type { Writeable } from '../../../shared/types/index.js'; import { FinancialAccountsTaxCategoriesProvider } from '../providers/financial-accounts-tax-categories.provider.js'; import { FinancialAccountsProvider } from '../providers/financial-accounts.provider.js'; import { FinancialBankAccountsProvider } from '../providers/financial-bank-accounts.provider.js'; import type { FinancialAccountsModule, IInsertFinancialAccountsParams, IInsertFinancialAccountTaxCategoriesParams, IUpdateFinancialAccountParams, } from '../types.js'; import { commonFinancialAccountFields, commonFinancialEntityFields, commonTransactionFields, } from './common.js'; export const financialAccountsResolvers: FinancialAccountsModule.Resolvers = { Query: { allFinancialAccounts: async (_, __, { injector }) => { return injector.get(FinancialAccountsProvider).getAllFinancialAccounts(); }, financialAccountsByOwner: async (_, { ownerId }, { injector }) => { return injector .get(FinancialAccountsProvider) .getFinancialAccountsByOwnerIdLoader.load(ownerId); }, financialAccount: async (_, { id }, { injector }) => { return injector .get(FinancialAccountsProvider) .getFinancialAccountByAccountIDLoader.load(id) .then(account => { if (!account) { throw new GraphQLError('Financial account not found'); } return account; }); }, }, Mutation: { deleteFinancialAccount: async (_, { id }, { injector }) => { return injector .get(FinancialAccountsProvider) .deleteFinancialAccount({ financialAccountId: id }) .then(() => true); }, createFinancialAccount: async (_, { input }, { injector }) => { try { const bankAccount: IInsertFinancialAccountsParams['bankAccounts'][number] = { accountNumber: input.number, name: input.name, privateBusiness: input.privateOrBusiness, ownerId: input.ownerId, type: input.type, }; const [account] = await injector .get(FinancialAccountsProvider) .insertFinancialAccounts({ bankAccounts: [bankAccount] }); if ( input.bankAccountDetails && Object.values(input.bankAccountDetails).some(v => v != null) ) { await injector.get(FinancialBankAccountsProvider).insertBankAccounts({ bankAccounts: [ { id: account.id, ownerId: input.ownerId, bankNumber: input.bankAccountDetails.bankNumber, branchNumber: input.bankAccountDetails.branchNumber, iban: input.bankAccountDetails.iban, swiftCode: input.bankAccountDetails.swiftCode, extendedBankNumber: input.bankAccountDetails.extendedBankNumber, partyPreferredIndication: input.bankAccountDetails.partyPreferredIndication, partyAccountInvolvementCode: input.bankAccountDetails.partyAccountInvolvementCode, accountDealDate: input.bankAccountDetails.accountDealDate, accountUpdateDate: input.bankAccountDetails.accountUpdateDate, metegDoarNet: input.bankAccountDetails.metegDoarNet, kodHarshaatPeilut: input.bankAccountDetails.kodHarshaatPeilut, accountClosingReasonCode: input.bankAccountDetails.accountClosingReasonCode, accountAgreementOpeningDate: input.bankAccountDetails.accountAgreementOpeningDate, serviceAuthorizationDesc: input.bankAccountDetails.serviceAuthorizationDesc, branchTypeCode: input.bankAccountDetails.branchTypeCode, mymailEntitlementSwitch: input.bankAccountDetails.mymailEntitlementSwitch, productLabel: input.bankAccountDetails.productLabel, }, ], }); } if (input.currencies && input.currencies.length > 0) { await injector .get(FinancialAccountsTaxCategoriesProvider) .insertFinancialAccountTaxCategories({ financialAccountsTaxCategories: input.currencies.map(c => ({ ownerId: input.ownerId, financialAccountId: account.id, currency: c.currency, taxCategoryId: c.taxCategoryId, })), }); } return account; } catch (error) { const message = 'Failed to create financial account'; console.error(message, error); throw new GraphQLError(message); } }, updateFinancialAccount: async (_, { id, fields }, { injector }) => { try { const updatedAccount: IUpdateFinancialAccountParams = { financialAccountId: id, accountNumber: fields.number, ownerId: fields.ownerId, privateBusiness: fields.privateOrBusiness, type: fields.type, }; const account = await injector .get(FinancialAccountsProvider) .updateFinancialAccount(updatedAccount); if ( fields.bankAccountDetails && Object.values(fields.bankAccountDetails).some(v => v != null) ) { await injector.get(FinancialBankAccountsProvider).updateBankAccount({ bankAccountId: id, accountAgreementOpeningDate: fields.bankAccountDetails.accountAgreementOpeningDate, accountClosingReasonCode: fields.bankAccountDetails.accountClosingReasonCode, accountDealDate: fields.bankAccountDetails.accountDealDate, accountUpdateDate: fields.bankAccountDetails.accountUpdateDate, bankNumber: fields.bankAccountDetails.bankNumber, branchNumber: fields.bankAccountDetails.branchNumber, branchTypeCode: fields.bankAccountDetails.branchTypeCode, extendedBankNumber: fields.bankAccountDetails.extendedBankNumber, iban: fields.bankAccountDetails.iban, swiftCode: fields.bankAccountDetails.swiftCode, kodHarshaatPeilut: fields.bankAccountDetails.kodHarshaatPeilut, metegDoarNet: fields.bankAccountDetails.metegDoarNet, mymailEntitlementSwitch: fields.bankAccountDetails.mymailEntitlementSwitch, partyAccountInvolvementCode: fields.bankAccountDetails.partyAccountInvolvementCode, partyPreferredIndication: fields.bankAccountDetails.partyPreferredIndication, productLabel: fields.bankAccountDetails.productLabel, serviceAuthorizationDesc: fields.bankAccountDetails.serviceAuthorizationDesc, }); } if (fields.currencies && fields.currencies.length > 0) { const currentTaxCategories = await injector .get(FinancialAccountsTaxCategoriesProvider) .getFinancialAccountTaxCategoriesByFinancialAccountIdLoader.load(account.id); if (currentTaxCategories.length > 0) { const updateTaxCategories: Promise<unknown>[] = []; // check for tax categories to delete - those that exist currently but are not included in the input const taxCategoriesToDelete = currentTaxCategories.filter( ctc => !fields.currencies!.some( inputTaxCategory => inputTaxCategory.currency === ctc.currency, ), ); if (taxCategoriesToDelete.length > 0) { updateTaxCategories.push( injector .get(FinancialAccountsTaxCategoriesProvider) .deleteFinancialAccountTaxCategories({ financialAccountId: account.id, currencies: taxCategoriesToDelete.map(tc => tc.currency), }), ); } const taxCategoriesToInsert: Writeable< IInsertFinancialAccountTaxCategoriesParams['financialAccountsTaxCategories'] > = []; fields.currencies.map(inputTaxCategory => { const currentTaxCategory = currentTaxCategories.find( ctc => ctc.currency === inputTaxCategory.currency, ); if (currentTaxCategory) { if (currentTaxCategory.tax_category_id !== inputTaxCategory.taxCategoryId) { // tax category changed for this currency, update it } updateTaxCategories.push( injector .get(FinancialAccountsTaxCategoriesProvider) .updateFinancialAccountTaxCategory({ financialAccountId: account.id, currency: inputTaxCategory.currency, taxCategoryId: inputTaxCategory.taxCategoryId, }), ); } else { // new tax category for this account, insert it taxCategoriesToInsert.push({ ownerId: account.owner_id, financialAccountId: account.id, currency: inputTaxCategory.currency, taxCategoryId: inputTaxCategory.taxCategoryId, }); } }); if (taxCategoriesToInsert.length > 0) { updateTaxCategories.push( injector .get(FinancialAccountsTaxCategoriesProvider) .insertFinancialAccountTaxCategories({ financialAccountsTaxCategories: taxCategoriesToInsert, }), ); } await Promise.all(updateTaxCategories); } else { // none existing,insert all await injector .get(FinancialAccountsTaxCategoriesProvider) .insertFinancialAccountTaxCategories({ financialAccountsTaxCategories: fields.currencies.map(c => ({ ownerId: account.owner_id, financialAccountId: account.id, currency: c.currency, taxCategoryId: c.taxCategoryId, })), }); } } return account; } catch (error) { const message = 'Failed to update financial account'; console.error(message, error); throw new GraphQLError(message); } }, }, CardFinancialAccount: { __isTypeOf: DbAccount => DbAccount.type === 'CREDIT_CARD', ...commonFinancialAccountFields, fourDigits: DbAccount => DbAccount.account_number, name: DbAccount => DbAccount.account_name ?? DbAccount.account_number, }, CryptoWalletFinancialAccount: { __isTypeOf: DbAccount => DbAccount.type === 'CRYPTO_WALLET', ...commonFinancialAccountFields, name: DbAccount => DbAccount.account_name ?? (DbAccount.account_number.length >= 20 ? DbAccount.account_number.slice(-8) : DbAccount.account_number), }, ForeignSecuritiesFinancialAccount: { __isTypeOf: DbAccount => DbAccount.type === 'FOREIGN_SECURITIES', ...commonFinancialAccountFields, name: DbAccount => DbAccount.account_name ?? DbAccount.account_number, }, BankDepositFinancialAccount: { __isTypeOf: DbAccount => DbAccount.type === 'BANK_DEPOSIT_ACCOUNT', ...commonFinancialAccountFields, name: DbAccount => DbAccount.account_name ?? DbAccount.account_number, }, ConversionTransaction: { ...commonTransactionFields, }, CommonTransaction: { ...commonTransactionFields, }, LtdFinancialEntity: { ...commonFinancialEntityFields, }, PersonalFinancialEntity: { ...commonFinancialEntityFields, }, };