diff --git a/packages/server/src/api/controllers/Banking/BankAccountsController.ts b/packages/server/src/api/controllers/Banking/BankAccountsController.ts index 424c28857..7f134fd75 100644 --- a/packages/server/src/api/controllers/Banking/BankAccountsController.ts +++ b/packages/server/src/api/controllers/Banking/BankAccountsController.ts @@ -1,9 +1,10 @@ import { Inject, Service } from 'typedi'; import { NextFunction, Request, Response, Router } from 'express'; +import { param, query } from 'express-validator'; import BaseController from '@/api/controllers/BaseController'; import { GetBankAccountSummary } from '@/services/Banking/BankAccounts/GetBankAccountSummary'; import { BankAccountsApplication } from '@/services/Banking/BankAccounts/BankAccountsApplication'; -import { param } from 'express-validator'; +import { GetPendingBankAccountTransactions } from '@/services/Cashflow/GetPendingBankAccountTransaction'; @Service() export class BankAccountsController extends BaseController { @@ -13,6 +14,9 @@ export class BankAccountsController extends BaseController { @Inject() private bankAccountsApp: BankAccountsApplication; + @Inject() + private getPendingTransactionsService: GetPendingBankAccountTransactions; + /** * Router constructor. */ @@ -20,6 +24,16 @@ export class BankAccountsController extends BaseController { const router = Router(); router.get('/:bankAccountId/meta', this.getBankAccountSummary.bind(this)); + router.get( + '/pending_transactions', + [ + query('account_id').optional().isNumeric().toInt(), + query('page').optional().isNumeric().toInt(), + query('page_size').optional().isNumeric().toInt(), + ], + this.validationResult, + this.getBankAccountsPendingTransactions.bind(this) + ); router.post( '/:bankAccountId/disconnect', this.disconnectBankAccount.bind(this) @@ -27,17 +41,13 @@ export class BankAccountsController extends BaseController { router.post('/:bankAccountId/update', this.refreshBankAccount.bind(this)); router.post( '/:bankAccountId/pause_feeds', - [ - param('bankAccountId').exists().isNumeric().toInt(), - ], + [param('bankAccountId').exists().isNumeric().toInt()], this.validationResult, this.pauseBankAccountFeeds.bind(this) ); router.post( '/:bankAccountId/resume_feeds', - [ - param('bankAccountId').exists().isNumeric().toInt(), - ], + [param('bankAccountId').exists().isNumeric().toInt()], this.validationResult, this.resumeBankAccountFeeds.bind(this) ); @@ -72,6 +82,30 @@ export class BankAccountsController extends BaseController { } } + /** + * Retrieves the bank account pending transactions. + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next + */ + async getBankAccountsPendingTransactions( + req: Request, + res: Response, + next: NextFunction + ) { + const { tenantId } = req; + + try { + const data = + await this.getPendingTransactionsService.getPendingTransactions( + tenantId + ); + return res.status(200).send(data); + } catch (error) { + next(error); + } + } + /** * Disonnect the given bank account. * @param {Request} req @@ -128,9 +162,9 @@ export class BankAccountsController extends BaseController { /** * Resumes the bank account feeds sync. - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next * @returns {Promise} */ async resumeBankAccountFeeds( @@ -155,9 +189,9 @@ export class BankAccountsController extends BaseController { /** * Pauses the bank account feeds sync. - * @param {Request} req - * @param {Response} res - * @param {NextFunction} next + * @param {Request} req + * @param {Response} res + * @param {NextFunction} next * @returns {Promise} */ async pauseBankAccountFeeds( diff --git a/packages/server/src/database/migrations/20240811121028_add_pending_column_to_uncategorized_transactions_table.js b/packages/server/src/database/migrations/20240811121028_add_pending_column_to_uncategorized_transactions_table.js new file mode 100644 index 000000000..73713b98b --- /dev/null +++ b/packages/server/src/database/migrations/20240811121028_add_pending_column_to_uncategorized_transactions_table.js @@ -0,0 +1,13 @@ +exports.up = function (knex) { + return knex.schema.table('uncategorized_cashflow_transactions', (table) => { + table.boolean('pending').defaultTo(false); + table.string('pending_plaid_transaction_id').nullable(); + }); +}; + +exports.down = function (knex) { + return knex.schema.table('uncategorized_cashflow_transactions', (table) => { + table.dropColumn('pending'); + table.dropColumn('pending_plaid_transaction_id'); + }); +}; diff --git a/packages/server/src/interfaces/CashFlow.ts b/packages/server/src/interfaces/CashFlow.ts index 4fe1e90c1..9e1d4bfd5 100644 --- a/packages/server/src/interfaces/CashFlow.ts +++ b/packages/server/src/interfaces/CashFlow.ts @@ -268,6 +268,8 @@ export interface CreateUncategorizedTransactionDTO { description?: string; referenceNo?: string | null; plaidTransactionId?: string | null; + pending?: boolean; + pendingPlaidTransactionId?: string | null; batch?: string; } diff --git a/packages/server/src/models/UncategorizedCashflowTransaction.ts b/packages/server/src/models/UncategorizedCashflowTransaction.ts index 218c35982..fbb737ccb 100644 --- a/packages/server/src/models/UncategorizedCashflowTransaction.ts +++ b/packages/server/src/models/UncategorizedCashflowTransaction.ts @@ -21,6 +21,7 @@ export default class UncategorizedCashflowTransaction extends mixin( plaidTransactionId!: string; recognizedTransactionId!: number; excludedAt: Date; + pending: boolean; /** * Table name. @@ -46,7 +47,8 @@ export default class UncategorizedCashflowTransaction extends mixin( 'isDepositTransaction', 'isWithdrawalTransaction', 'isRecognized', - 'isExcluded' + 'isExcluded', + 'isPending', ]; } @@ -99,6 +101,14 @@ export default class UncategorizedCashflowTransaction extends mixin( return !!this.excludedAt; } + /** + * Detarmines whether the transaction is pending. + * @returns {boolean} + */ + public get isPending(): boolean { + return !!this.pending; + } + /** * Model modifiers. */ @@ -143,6 +153,20 @@ export default class UncategorizedCashflowTransaction extends mixin( query.whereNull('categorizeRefType'); query.whereNull('categorizeRefId'); }, + + /** + * Filters the not pending transactions. + */ + notPending(query) { + query.where('pending', false); + }, + + /** + * Filters the pending transactions. + */ + pending(query) { + query.where('pending', true); + }, }; } diff --git a/packages/server/src/services/Banking/BankAccounts/GetBankAccountSummary.ts b/packages/server/src/services/Banking/BankAccounts/GetBankAccountSummary.ts index 29c68abb6..6c66c2a5e 100644 --- a/packages/server/src/services/Banking/BankAccounts/GetBankAccountSummary.ts +++ b/packages/server/src/services/Banking/BankAccounts/GetBankAccountSummary.ts @@ -69,12 +69,22 @@ export class GetBankAccountSummary { q.count('uncategorized_cashflow_transactions.id as total'); q.first(); }); - + // Retrieves excluded transactions count. const excludedTransactionsCount = await UncategorizedCashflowTransaction.query().onBuild((q) => { q.where('accountId', bankAccountId); q.modify('excluded'); + // Count the results. + q.count('uncategorized_cashflow_transactions.id as total'); + q.first(); + }); + // Retrieves the pending transactions count. + const pendingTransactionsCount = + await UncategorizedCashflowTransaction.query().onBuild((q) => { + q.where('accountId', bankAccountId); + q.modify('pending'); + // Count the results. q.count('uncategorized_cashflow_transactions.id as total'); q.first(); @@ -83,14 +93,15 @@ export class GetBankAccountSummary { const totalUncategorizedTransactions = uncategorizedTranasctionsCount?.total || 0; const totalRecognizedTransactions = recognizedTransactionsCount?.total || 0; - const totalExcludedTransactions = excludedTransactionsCount?.total || 0; + const totalPendingTransactions = pendingTransactionsCount?.total || 0; return { name: bankAccount.name, totalUncategorizedTransactions, totalRecognizedTransactions, totalExcludedTransactions, + totalPendingTransactions, }; } } diff --git a/packages/server/src/services/Banking/Plaid/PlaidSyncDB.ts b/packages/server/src/services/Banking/Plaid/PlaidSyncDB.ts index aed2fc945..4c1973f8b 100644 --- a/packages/server/src/services/Banking/Plaid/PlaidSyncDB.ts +++ b/packages/server/src/services/Banking/Plaid/PlaidSyncDB.ts @@ -25,6 +25,7 @@ import { Knex } from 'knex'; import uniqid from 'uniqid'; import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; import events from '@/subscribers/events'; +import { RemovePendingUncategorizedTransaction } from '@/services/Cashflow/RemovePendingUncategorizedTransaction'; const CONCURRENCY_ASYNC = 10; @@ -40,7 +41,7 @@ export class PlaidSyncDb { private cashflowApp: CashflowApplication; @Inject() - private deleteCashflowTransactionService: DeleteCashflowTransaction; + private removePendingTransaction: RemovePendingUncategorizedTransaction; @Inject() private eventPublisher: EventPublisher; @@ -185,21 +186,22 @@ export class PlaidSyncDb { plaidTransactionsIds: string[], trx?: Knex.Transaction ) { - const { CashflowTransaction } = this.tenancy.models(tenantId); + const { UncategorizedCashflowTransaction } = this.tenancy.models(tenantId); - const cashflowTransactions = await CashflowTransaction.query(trx).whereIn( - 'plaidTransactionId', - plaidTransactionsIds - ); - const cashflowTransactionsIds = cashflowTransactions.map( + const uncategorizedTransactions = + await UncategorizedCashflowTransaction.query(trx).whereIn( + 'plaidTransactionId', + plaidTransactionsIds + ); + const uncategorizedTransactionsIds = uncategorizedTransactions.map( (trans) => trans.id ); await bluebird.map( - cashflowTransactionsIds, - (transactionId: number) => - this.deleteCashflowTransactionService.deleteCashflowTransaction( + uncategorizedTransactionsIds, + (uncategorizedTransactionId: number) => + this.removePendingTransaction.removePendingTransaction( tenantId, - transactionId, + uncategorizedTransactionId, trx ), { concurrency: CONCURRENCY_ASYNC } diff --git a/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts b/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts index 3265cc2ba..547aac45d 100644 --- a/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts +++ b/packages/server/src/services/Banking/Plaid/PlaidUpdateTransactions.ts @@ -73,6 +73,12 @@ export class PlaidUpdateTransactions { item, trx ); + // Sync removed transactions. + await this.plaidSync.syncRemoveTransactions( + tenantId, + removed?.map((r) => r.transaction_id), + trx + ); // Sync bank account transactions. await this.plaidSync.syncAccountsTransactions( tenantId, diff --git a/packages/server/src/services/Banking/Plaid/utils.ts b/packages/server/src/services/Banking/Plaid/utils.ts index 395b4346f..2804279c5 100644 --- a/packages/server/src/services/Banking/Plaid/utils.ts +++ b/packages/server/src/services/Banking/Plaid/utils.ts @@ -3,11 +3,11 @@ import { Item as PlaidItem, Institution as PlaidInstitution, AccountBase as PlaidAccount, + TransactionBase as PlaidTransactionBase, } from 'plaid'; import { CreateUncategorizedTransactionDTO, IAccountCreateDTO, - PlaidTransaction, } from '@/interfaces'; /** @@ -48,7 +48,7 @@ export const transformPlaidAccountToCreateAccount = R.curry( export const transformPlaidTrxsToCashflowCreate = R.curry( ( cashflowAccountId: number, - plaidTranasction: PlaidTransaction + plaidTranasction: PlaidTransactionBase ): CreateUncategorizedTransactionDTO => { return { date: plaidTranasction.date, @@ -64,6 +64,8 @@ export const transformPlaidTrxsToCashflowCreate = R.curry( accountId: cashflowAccountId, referenceNo: plaidTranasction.payment_meta?.reference_number, plaidTransactionId: plaidTranasction.transaction_id, + pending: plaidTranasction.pending, + pendingPlaidTransactionId: plaidTranasction.pending_transaction_id, }; } ); diff --git a/packages/server/src/services/Cashflow/GetPendingBankAccountTransaction.ts b/packages/server/src/services/Cashflow/GetPendingBankAccountTransaction.ts new file mode 100644 index 000000000..34bd5ad31 --- /dev/null +++ b/packages/server/src/services/Cashflow/GetPendingBankAccountTransaction.ts @@ -0,0 +1,53 @@ +import { Inject } from 'typedi'; +import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable'; +import HasTenancyService from '../Tenancy/TenancyService'; +import { GetPendingBankAccountTransactionTransformer } from './GetPendingBankAccountTransactionTransformer'; + +export class GetPendingBankAccountTransactions { + @Inject() + private tenancy: HasTenancyService; + + @Inject() + private transformer: TransformerInjectable; + + /** + * Retrieves the given bank accounts pending transaction. + * @param {number} tenantId + * @param {number} bankAccountId + */ + async getPendingTransactions( + tenantId: number, + filter?: GetPendingTransactionsQuery + ) { + const { UncategorizedCashflowTransaction } = this.tenancy.models(tenantId); + + const _filter = { + page: 1, + pageSize: 20, + ...filter, + }; + const { results, pagination } = + await UncategorizedCashflowTransaction.query() + .onBuild((q) => { + q.modify('pending'); + + if (_filter?.accountId) { + q.where('accountId', _filter.accountId); + } + }) + .pagination(_filter.page - 1, _filter.pageSize); + + const data = this.transformer.transform( + tenantId, + results, + new GetPendingBankAccountTransactionTransformer() + ); + return { data, pagination }; + } +} + +interface GetPendingTransactionsQuery { + page?: number; + pageSize?: number; + accountId?: number; +} diff --git a/packages/server/src/services/Cashflow/GetPendingBankAccountTransactionTransformer.ts b/packages/server/src/services/Cashflow/GetPendingBankAccountTransactionTransformer.ts new file mode 100644 index 000000000..d388546a4 --- /dev/null +++ b/packages/server/src/services/Cashflow/GetPendingBankAccountTransactionTransformer.ts @@ -0,0 +1,73 @@ +import { Transformer } from '@/lib/Transformer/Transformer'; +import { formatNumber } from '@/utils'; + +export class GetPendingBankAccountTransactionTransformer extends Transformer { + /** + * Include these attributes to sale invoice object. + * @returns {string[]} + */ + public includeAttributes = (): string[] => { + return [ + 'formattedAmount', + 'formattedDate', + 'formattedDepositAmount', + 'formattedWithdrawalAmount', + ]; + }; + + /** + * Exclude all attributes. + * @returns {Array} + */ + public excludeAttributes = (): string[] => { + return []; + }; + + /** + * Formattes the transaction date. + * @param transaction + * @returns {string} + */ + public formattedDate(transaction) { + return this.formatDate(transaction.date); + } + + /** + * Formatted amount. + * @param transaction + * @returns {string} + */ + public formattedAmount(transaction) { + return formatNumber(transaction.amount, { + currencyCode: transaction.currencyCode, + }); + } + + /** + * Formatted deposit amount. + * @param transaction + * @returns {string} + */ + protected formattedDepositAmount(transaction) { + if (transaction.isDepositTransaction) { + return formatNumber(transaction.deposit, { + currencyCode: transaction.currencyCode, + }); + } + return ''; + } + + /** + * Formatted withdrawal amount. + * @param transaction + * @returns {string} + */ + protected formattedWithdrawalAmount(transaction) { + if (transaction.isWithdrawalTransaction) { + return formatNumber(transaction.withdrawal, { + currencyCode: transaction.currencyCode, + }); + } + return ''; + } +} diff --git a/packages/server/src/services/Cashflow/RemovePendingUncategorizedTransaction.ts b/packages/server/src/services/Cashflow/RemovePendingUncategorizedTransaction.ts new file mode 100644 index 000000000..15a75ae23 --- /dev/null +++ b/packages/server/src/services/Cashflow/RemovePendingUncategorizedTransaction.ts @@ -0,0 +1,58 @@ +import { Knex } from 'knex'; +import { Inject, Service } from 'typedi'; +import HasTenancyService from '../Tenancy/TenancyService'; +import UnitOfWork from '../UnitOfWork'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from './constants'; + +@Service() +export class RemovePendingUncategorizedTransaction { + @Inject() + private tenancy: HasTenancyService; + + @Inject() + private uow: UnitOfWork; + + @Inject() + private eventPublisher: EventPublisher; + + /** + * REmoves the pending uncategorized transaction. + * @param {number} tenantId - + * @param {number} uncategorizedTransactionId - + * @param {Knex.Transaction} trx - + * @returns {Promise} + */ + public async removePendingTransaction( + tenantId: number, + uncategorizedTransactionId: number, + trx?: Knex.Transaction + ): Promise { + const { UncategorizedCashflowTransaction } = this.tenancy.models(tenantId); + + const pendingTransaction = await UncategorizedCashflowTransaction.query(trx) + .findById(uncategorizedTransactionId) + .throwIfNotFound(); + + if (!pendingTransaction.isPending) { + throw new ServiceError(ERRORS.TRANSACTION_NOT_PENDING); + } + return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => { + await this.eventPublisher.emitAsync( + events.bankTransactions.onPendingRemoving, + { tenantId, uncategorizedTransactionId, trx } + ); + // Removes the pending uncategorized transaction. + await UncategorizedCashflowTransaction.query(trx) + .findById(uncategorizedTransactionId) + .delete(); + + await this.eventPublisher.emitAsync( + events.bankTransactions.onPendingRemoved, + { tenantId, uncategorizedTransactionId, trx } + ); + }); + } +} diff --git a/packages/server/src/services/Cashflow/constants.ts b/packages/server/src/services/Cashflow/constants.ts index f9b8e24e8..50b35526a 100644 --- a/packages/server/src/services/Cashflow/constants.ts +++ b/packages/server/src/services/Cashflow/constants.ts @@ -15,10 +15,10 @@ export const ERRORS = { 'UNCATEGORIZED_TRANSACTION_TYPE_INVALID', CANNOT_DELETE_TRANSACTION_CONVERTED_FROM_UNCATEGORIZED: 'CANNOT_DELETE_TRANSACTION_CONVERTED_FROM_UNCATEGORIZED', - - CANNOT_CATEGORIZE_EXCLUDED_TRANSACTION: 'CANNOT_CATEGORIZE_EXCLUDED_TRANSACTION', - TRANSACTION_NOT_CATEGORIZED: 'TRANSACTION_NOT_CATEGORIZED' - + CANNOT_CATEGORIZE_EXCLUDED_TRANSACTION: + 'CANNOT_CATEGORIZE_EXCLUDED_TRANSACTION', + TRANSACTION_NOT_CATEGORIZED: 'TRANSACTION_NOT_CATEGORIZED', + TRANSACTION_NOT_PENDING: 'TRANSACTION_NOT_PENDING', }; export enum CASHFLOW_DIRECTION { diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index c72a2e7d3..2299df01b 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -659,6 +659,9 @@ export default { onUnexcluding: 'onBankTransactionUnexcluding', onUnexcluded: 'onBankTransactionUnexcluded', + + onPendingRemoving: 'onBankTransactionPendingRemoving', + onPendingRemoved: 'onBankTransactionPendingRemoved', }, bankAccount: { diff --git a/packages/webapp/src/constants/query-keys/banking.ts b/packages/webapp/src/constants/query-keys/banking.ts index 7164470e2..1a69341b0 100644 --- a/packages/webapp/src/constants/query-keys/banking.ts +++ b/packages/webapp/src/constants/query-keys/banking.ts @@ -7,4 +7,5 @@ export const BANK_QUERY_KEY = { 'RECOGNIZED_BANK_TRANSACTIONS_INFINITY', BANK_ACCOUNT_SUMMARY_META: 'BANK_ACCOUNT_SUMMARY_META', AUTOFILL_CATEGORIZE_BANK_TRANSACTION: 'AUTOFILL_CATEGORIZE_BANK_TRANSACTION', + PENDING_BANK_ACCOUNT_TRANSACTIONS: 'PENDING_BANK_ACCOUNT_TRANSACTIONS' }; diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsFilterTabs.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsFilterTabs.tsx index 3cd798feb..1c1320b54 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsFilterTabs.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsFilterTabs.tsx @@ -20,7 +20,8 @@ export function AccountTransactionsFilterTabs() { const hasUncategorizedTransx = useMemo( () => bankAccountMetaSummary?.totalUncategorizedTransactions > 0 || - bankAccountMetaSummary?.totalExcludedTransactions > 0, + bankAccountMetaSummary?.totalExcludedTransactions > 0 || + bankAccountMetaSummary?.totalPendingTransactions > 0, [bankAccountMetaSummary], ); diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx index 2272c7e54..21e82f9d9 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/AccountTransactionsUncategorizeFilter.tsx @@ -1,4 +1,6 @@ // @ts-nocheck +import * as R from 'ramda'; +import { useMemo } from 'react'; import { useAppQueryString } from '@/hooks'; import { Group } from '@/components'; import { useAccountTransactionsContext } from './AccountTransactionsProvider'; @@ -12,31 +14,49 @@ export function AccountTransactionsUncategorizeFilter() { bankAccountMetaSummary?.totalUncategorizedTransactions; const totalRecognized = bankAccountMetaSummary?.totalRecognizedTransactions; + const totalPending = bankAccountMetaSummary?.totalPendingTransactions; + const handleTabsChange = (value) => { setLocationQuery({ uncategorizedFilter: value }); }; + const options = useMemo( + () => + R.when( + () => totalPending > 0, + R.append({ + value: 'pending', + label: ( + <> + Pending ({totalPending}) + + ), + }), + )([ + { + value: 'all', + label: ( + <> + All ({totalUncategorized}) + + ), + }, + { + value: 'recognized', + label: ( + <> + Recognized ({totalRecognized}) + + ), + }, + ]), + [totalPending, totalRecognized, totalUncategorized], + ); + return ( - All ({totalUncategorized}) - - ), - }, - { - value: 'recognized', - label: ( - <> - Recognized ({totalRecognized}) - - ), - }, - ]} + options={options} value={locationQuery?.uncategorizedFilter || 'all'} onValueChange={handleTabsChange} /> diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/AllTransactionsUncategorized.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/AllTransactionsUncategorized.tsx index ad903b06d..54996f1a3 100644 --- a/packages/webapp/src/containers/CashFlow/AccountTransactions/AllTransactionsUncategorized.tsx +++ b/packages/webapp/src/containers/CashFlow/AccountTransactions/AllTransactionsUncategorized.tsx @@ -70,6 +70,8 @@ function AccountTransactionsSwitcher() { case 'all': default: return ; + case 'pending': + return null; } } diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/PendingTransactions/PendingTransactionsTable.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/PendingTransactions/PendingTransactionsTable.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/packages/webapp/src/containers/CashFlow/AccountTransactions/PendingTransactions/PendingTransactionsTableBoot.tsx b/packages/webapp/src/containers/CashFlow/AccountTransactions/PendingTransactions/PendingTransactionsTableBoot.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/packages/webapp/src/hooks/query/bank-transaction.ts b/packages/webapp/src/hooks/query/bank-transaction.ts new file mode 100644 index 000000000..8cdfb88de --- /dev/null +++ b/packages/webapp/src/hooks/query/bank-transaction.ts @@ -0,0 +1,28 @@ +// @ts-nocheck +import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query'; +import useApiRequest from '../useRequest'; +import { BANK_QUERY_KEY } from '@/constants/query-keys/banking'; + +interface GetBankRuleRes {} + +/** + * Retrieve the given bank rule. + * @param {number} bankRuleId - + * @param {UseQueryOptions} options - + * @returns {UseQueryResult} + */ +export function usePendingBankAccountTransactions( + bankRuleId: number, + options?: UseQueryOptions, +): UseQueryResult { + const apiRequest = useApiRequest(); + + return useQuery( + [BANK_QUERY_KEY.PENDING_BANK_ACCOUNT_TRANSACTIONS], + () => + apiRequest + .get(`/banking/bank_account/pending_transactions`) + .then((res) => res.data), + { ...options }, + ); +}