mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
Merge pull request #563 from bigcapitalhq/pause-resume-bank-feeds-syncing
feat: pause/resume bank account feeds syncing
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { NextFunction, Request, Response, Router } from 'express';
|
import { NextFunction, Request, Response, Router } from 'express';
|
||||||
import BaseController from '@/api/controllers/BaseController';
|
import BaseController from '@/api/controllers/BaseController';
|
||||||
import { CashflowApplication } from '@/services/Cashflow/CashflowApplication';
|
|
||||||
import { GetBankAccountSummary } from '@/services/Banking/BankAccounts/GetBankAccountSummary';
|
import { GetBankAccountSummary } from '@/services/Banking/BankAccounts/GetBankAccountSummary';
|
||||||
import { BankAccountsApplication } from '@/services/Banking/BankAccounts/BankAccountsApplication';
|
import { BankAccountsApplication } from '@/services/Banking/BankAccounts/BankAccountsApplication';
|
||||||
|
import { param } from 'express-validator';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class BankAccountsController extends BaseController {
|
export class BankAccountsController extends BaseController {
|
||||||
@@ -25,6 +25,22 @@ export class BankAccountsController extends BaseController {
|
|||||||
this.disconnectBankAccount.bind(this)
|
this.disconnectBankAccount.bind(this)
|
||||||
);
|
);
|
||||||
router.post('/:bankAccountId/update', this.refreshBankAccount.bind(this));
|
router.post('/:bankAccountId/update', this.refreshBankAccount.bind(this));
|
||||||
|
router.post(
|
||||||
|
'/:bankAccountId/pause_feeds',
|
||||||
|
[
|
||||||
|
param('bankAccountId').exists().isNumeric().toInt(),
|
||||||
|
],
|
||||||
|
this.validationResult,
|
||||||
|
this.pauseBankAccountFeeds.bind(this)
|
||||||
|
);
|
||||||
|
router.post(
|
||||||
|
'/:bankAccountId/resume_feeds',
|
||||||
|
[
|
||||||
|
param('bankAccountId').exists().isNumeric().toInt(),
|
||||||
|
],
|
||||||
|
this.validationResult,
|
||||||
|
this.resumeBankAccountFeeds.bind(this)
|
||||||
|
);
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
}
|
}
|
||||||
@@ -109,4 +125,58 @@ export class BankAccountsController extends BaseController {
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes the bank account feeds sync.
|
||||||
|
* @param {Request} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
* @returns {Promise<Response | void>}
|
||||||
|
*/
|
||||||
|
async resumeBankAccountFeeds(
|
||||||
|
req: Request<{ bankAccountId: number }>,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) {
|
||||||
|
const { bankAccountId } = req.params;
|
||||||
|
const { tenantId } = req;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.bankAccountsApp.resumeBankAccount(tenantId, bankAccountId);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
message: 'The bank account feeds syncing has been resumed.',
|
||||||
|
id: bankAccountId,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the bank account feeds sync.
|
||||||
|
* @param {Request} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
* @returns {Promise<Response | void>}
|
||||||
|
*/
|
||||||
|
async pauseBankAccountFeeds(
|
||||||
|
req: Request<{ bankAccountId: number }>,
|
||||||
|
res: Response,
|
||||||
|
next: NextFunction
|
||||||
|
) {
|
||||||
|
const { bankAccountId } = req.params;
|
||||||
|
const { tenantId } = req;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.bankAccountsApp.pauseBankAccount(tenantId, bankAccountId);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
message: 'The bank account feeds syncing has been paused.',
|
||||||
|
id: bankAccountId,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('plaid_items', (table) => {
|
||||||
|
table.datetime('paused_at');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.table('plaid_items', (table) => {
|
||||||
|
table.dropColumn('paused_at');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import TenantModel from 'models/TenantModel';
|
import TenantModel from 'models/TenantModel';
|
||||||
|
|
||||||
export default class PlaidItem extends TenantModel {
|
export default class PlaidItem extends TenantModel {
|
||||||
|
pausedAt: Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table name.
|
* Table name.
|
||||||
*/
|
*/
|
||||||
@@ -21,4 +23,19 @@ export default class PlaidItem extends TenantModel {
|
|||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual attributes.
|
||||||
|
*/
|
||||||
|
static get virtualAttributes() {
|
||||||
|
return ['isPaused'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the Plaid item feeds syncing is paused.
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
get isPaused() {
|
||||||
|
return !!this.pausedAt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,18 @@ export class AccountTransformer extends Transformer {
|
|||||||
'flattenName',
|
'flattenName',
|
||||||
'bankBalanceFormatted',
|
'bankBalanceFormatted',
|
||||||
'lastFeedsUpdatedAtFormatted',
|
'lastFeedsUpdatedAtFormatted',
|
||||||
|
'isFeedsPaused',
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude attributes.
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
public excludeAttributes = (): string[] => {
|
||||||
|
return ['plaidItem'];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the flatten name with all dependants accounts names.
|
* Retrieves the flatten name with all dependants accounts names.
|
||||||
* @param {IAccount} account -
|
* @param {IAccount} account -
|
||||||
@@ -66,6 +75,15 @@ export class AccountTransformer extends Transformer {
|
|||||||
return this.formatDate(account.lastFeedsUpdatedAt);
|
return this.formatDate(account.lastFeedsUpdatedAt);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the bank account connection is paused.
|
||||||
|
* @param account
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
protected isFeedsPaused = (account: any): boolean => {
|
||||||
|
return account.plaidItem?.isPaused || false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformes the accounts collection to flat or nested array.
|
* Transformes the accounts collection to flat or nested array.
|
||||||
* @param {IAccount[]}
|
* @param {IAccount[]}
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ export class GetAccount {
|
|||||||
const { accountRepository } = this.tenancy.repositories(tenantId);
|
const { accountRepository } = this.tenancy.repositories(tenantId);
|
||||||
|
|
||||||
// Find the given account or throw not found error.
|
// Find the given account or throw not found error.
|
||||||
const account = await Account.query().findById(accountId).throwIfNotFound();
|
const account = await Account.query()
|
||||||
|
.findById(accountId)
|
||||||
|
.withGraphFetched('plaidItem')
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
const accountsGraph = await accountRepository.getDependencyGraph();
|
const accountsGraph = await accountRepository.getDependencyGraph();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { DisconnectBankAccount } from './DisconnectBankAccount';
|
import { DisconnectBankAccount } from './DisconnectBankAccount';
|
||||||
import { RefreshBankAccountService } from './RefreshBankAccount';
|
import { RefreshBankAccountService } from './RefreshBankAccount';
|
||||||
|
import { PauseBankAccountFeeds } from './PauseBankAccountFeeds';
|
||||||
|
import { ResumeBankAccountFeeds } from './ResumeBankAccountFeeds';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class BankAccountsApplication {
|
export class BankAccountsApplication {
|
||||||
@@ -10,6 +12,12 @@ export class BankAccountsApplication {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private refreshBankAccountService: RefreshBankAccountService;
|
private refreshBankAccountService: RefreshBankAccountService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private resumeBankAccountFeedsService: ResumeBankAccountFeeds;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private pauseBankAccountFeedsService: PauseBankAccountFeeds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects the given bank account.
|
* Disconnects the given bank account.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -27,7 +35,7 @@ export class BankAccountsApplication {
|
|||||||
* Refresh the bank transactions of the given bank account.
|
* Refresh the bank transactions of the given bank account.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number} bankAccountId
|
* @param {number} bankAccountId
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async refreshBankAccount(tenantId: number, bankAccountId: number) {
|
async refreshBankAccount(tenantId: number, bankAccountId: number) {
|
||||||
return this.refreshBankAccountService.refreshBankAccount(
|
return this.refreshBankAccountService.refreshBankAccount(
|
||||||
@@ -35,4 +43,30 @@ export class BankAccountsApplication {
|
|||||||
bankAccountId
|
bankAccountId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the feeds sync of the given bank account.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} bankAccountId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async pauseBankAccount(tenantId: number, bankAccountId: number) {
|
||||||
|
return this.pauseBankAccountFeedsService.pauseBankAccountFeeds(
|
||||||
|
tenantId,
|
||||||
|
bankAccountId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes the feeds sync of the given bank account.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} bankAccountId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async resumeBankAccount(tenantId: number, bankAccountId: number) {
|
||||||
|
return this.resumeBankAccountFeedsService.resumeBankAccountFeeds(
|
||||||
|
tenantId,
|
||||||
|
bankAccountId
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
|
import { ServiceError } from '@/exceptions';
|
||||||
|
import { ERRORS } from './types';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class PauseBankAccountFeeds {
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private uow: UnitOfWork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the bankfeed syncing of the given bank account.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} bankAccountId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public async pauseBankAccountFeeds(tenantId: number, bankAccountId: number) {
|
||||||
|
const { Account, PlaidItem } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const oldAccount = await Account.query()
|
||||||
|
.findById(bankAccountId)
|
||||||
|
.withGraphFetched('plaidItem')
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
|
// Can't continue if the bank account is not connected.
|
||||||
|
if (!oldAccount.plaidItem) {
|
||||||
|
throw new ServiceError(ERRORS.BANK_ACCOUNT_NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
// Cannot continue if the bank account feeds is already paused.
|
||||||
|
if (oldAccount.plaidItem.isPaused) {
|
||||||
|
throw new ServiceError(ERRORS.BANK_ACCOUNT_FEEDS_ALREADY_PAUSED);
|
||||||
|
}
|
||||||
|
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||||
|
await PlaidItem.query(trx).findById(oldAccount.plaidItem.id).patch({
|
||||||
|
pausedAt: new Date(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
import UnitOfWork from '@/services/UnitOfWork';
|
||||||
|
import { ServiceError } from '@/exceptions';
|
||||||
|
import { ERRORS } from './types';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class ResumeBankAccountFeeds {
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private uow: UnitOfWork;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes the bank feeds syncing of the bank account.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {number} bankAccountId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
public async resumeBankAccountFeeds(tenantId: number, bankAccountId: number) {
|
||||||
|
const { Account, PlaidItem } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const oldAccount = await Account.query()
|
||||||
|
.findById(bankAccountId)
|
||||||
|
.withGraphFetched('plaidItem');
|
||||||
|
|
||||||
|
// Can't continue if the bank account is not connected.
|
||||||
|
if (!oldAccount.plaidItem) {
|
||||||
|
throw new ServiceError(ERRORS.BANK_ACCOUNT_NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
// Cannot continue if the bank account feeds is already paused.
|
||||||
|
if (!oldAccount.plaidItem.isPaused) {
|
||||||
|
throw new ServiceError(ERRORS.BANK_ACCOUNT_FEEDS_ALREADY_RESUMED);
|
||||||
|
}
|
||||||
|
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||||
|
await PlaidItem.query(trx).findById(oldAccount.plaidItem.id).patch({
|
||||||
|
pausedAt: null,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,4 +14,6 @@ export interface IBankAccountDisconnectedEventPayload {
|
|||||||
|
|
||||||
export const ERRORS = {
|
export const ERRORS = {
|
||||||
BANK_ACCOUNT_NOT_CONNECTED: 'BANK_ACCOUNT_NOT_CONNECTED',
|
BANK_ACCOUNT_NOT_CONNECTED: 'BANK_ACCOUNT_NOT_CONNECTED',
|
||||||
|
BANK_ACCOUNT_FEEDS_ALREADY_PAUSED: 'BANK_ACCOUNT_FEEDS_ALREADY_PAUSED',
|
||||||
|
BANK_ACCOUNT_FEEDS_ALREADY_RESUMED: 'BANK_ACCOUNT_FEEDS_ALREADY_RESUMED',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { PlaidUpdateTransactions } from './PlaidUpdateTransactions';
|
import { PlaidUpdateTransactions } from './PlaidUpdateTransactions';
|
||||||
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class PlaidWebooks {
|
export class PlaidWebooks {
|
||||||
@Inject()
|
@Inject()
|
||||||
private updateTransactionsService: PlaidUpdateTransactions;
|
private updateTransactionsService: PlaidUpdateTransactions;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private tenancy: HasTenancyService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens to Plaid webhooks
|
* Listens to Plaid webhooks
|
||||||
* @param {number} tenantId - Tenant Id.
|
* @param {number} tenantId - Tenant Id.
|
||||||
@@ -61,7 +65,7 @@ export class PlaidWebooks {
|
|||||||
plaidItemId: string
|
plaidItemId: string
|
||||||
): void {
|
): void {
|
||||||
console.log(
|
console.log(
|
||||||
`WEBHOOK: TRANSACTIONS: ${webhookCode}: Plaid_item_id ${plaidItemId}: ${additionalInfo}`
|
`PLAID WEBHOOK: TRANSACTIONS: ${webhookCode}: Plaid_item_id ${plaidItemId}: ${additionalInfo}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,8 +82,21 @@ export class PlaidWebooks {
|
|||||||
plaidItemId: string,
|
plaidItemId: string,
|
||||||
webhookCode: string
|
webhookCode: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const { PlaidItem } = this.tenancy.models(tenantId);
|
||||||
|
const plaidItem = await PlaidItem.query()
|
||||||
|
.findById(plaidItemId)
|
||||||
|
.throwIfNotFound();
|
||||||
|
|
||||||
switch (webhookCode) {
|
switch (webhookCode) {
|
||||||
case 'SYNC_UPDATES_AVAILABLE': {
|
case 'SYNC_UPDATES_AVAILABLE': {
|
||||||
|
if (plaidItem.isPaused) {
|
||||||
|
this.serverLogAndEmitSocket(
|
||||||
|
'Plaid item syncing is paused.',
|
||||||
|
webhookCode,
|
||||||
|
plaidItemId
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Fired when new transactions data becomes available.
|
// Fired when new transactions data becomes available.
|
||||||
const { addedCount, modifiedCount, removedCount } =
|
const { addedCount, modifiedCount, removedCount } =
|
||||||
await this.updateTransactionsService.updateTransactions(
|
await this.updateTransactionsService.updateTransactions(
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import ReceiptMailDialog from '@/containers/Sales/Receipts/ReceiptMailDialog/Rec
|
|||||||
import PaymentMailDialog from '@/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog';
|
import PaymentMailDialog from '@/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog';
|
||||||
import { ExportDialog } from '@/containers/Dialogs/ExportDialog';
|
import { ExportDialog } from '@/containers/Dialogs/ExportDialog';
|
||||||
import { RuleFormDialog } from '@/containers/Banking/Rules/RuleFormDialog/RuleFormDialog';
|
import { RuleFormDialog } from '@/containers/Banking/Rules/RuleFormDialog/RuleFormDialog';
|
||||||
|
import { DisconnectBankAccountDialog } from '@/containers/CashFlow/AccountTransactions/dialogs/DisconnectBankAccountDialog/DisconnectBankAccountDialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialogs container.
|
* Dialogs container.
|
||||||
@@ -148,7 +149,10 @@ export default function DialogsContainer() {
|
|||||||
<ReceiptMailDialog dialogName={DialogsName.ReceiptMail} />
|
<ReceiptMailDialog dialogName={DialogsName.ReceiptMail} />
|
||||||
<PaymentMailDialog dialogName={DialogsName.PaymentMail} />
|
<PaymentMailDialog dialogName={DialogsName.PaymentMail} />
|
||||||
<ExportDialog dialogName={DialogsName.Export} />
|
<ExportDialog dialogName={DialogsName.Export} />
|
||||||
<RuleFormDialog dialogName={DialogsName.BankRuleForm} />
|
<RuleFormDialog dialogName={DialogsName.BankRuleForm} />
|
||||||
|
<DisconnectBankAccountDialog
|
||||||
|
dialogName={DialogsName.DisconnectBankAccountConfirmation}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,5 +75,6 @@ export enum DialogsName {
|
|||||||
GeneralLedgerPdfPreview = 'GeneralLedgerPdfPreview',
|
GeneralLedgerPdfPreview = 'GeneralLedgerPdfPreview',
|
||||||
SalesTaxLiabilitySummaryPdfPreview = 'SalesTaxLiabilitySummaryPdfPreview',
|
SalesTaxLiabilitySummaryPdfPreview = 'SalesTaxLiabilitySummaryPdfPreview',
|
||||||
Export = 'Export',
|
Export = 'Export',
|
||||||
BankRuleForm = 'BankRuleForm'
|
BankRuleForm = 'BankRuleForm',
|
||||||
|
DisconnectBankAccountConfirmation = 'DisconnectBankAccountConfirmation',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import TaxRatesAlerts from '@/containers/TaxRates/alerts';
|
|||||||
import { CashflowAlerts } from '../CashFlow/CashflowAlerts';
|
import { CashflowAlerts } from '../CashFlow/CashflowAlerts';
|
||||||
import { BankRulesAlerts } from '../Banking/Rules/RulesList/BankRulesAlerts';
|
import { BankRulesAlerts } from '../Banking/Rules/RulesList/BankRulesAlerts';
|
||||||
import { SubscriptionAlerts } from '../Subscriptions/alerts/alerts';
|
import { SubscriptionAlerts } from '../Subscriptions/alerts/alerts';
|
||||||
|
import { BankAccountAlerts } from '@/containers/CashFlow/AccountTransactions/alerts';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
...AccountsAlerts,
|
...AccountsAlerts,
|
||||||
@@ -58,5 +59,6 @@ export default [
|
|||||||
...TaxRatesAlerts,
|
...TaxRatesAlerts,
|
||||||
...CashflowAlerts,
|
...CashflowAlerts,
|
||||||
...BankRulesAlerts,
|
...BankRulesAlerts,
|
||||||
...SubscriptionAlerts
|
...SubscriptionAlerts,
|
||||||
|
...BankAccountAlerts,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -40,12 +40,13 @@ import withSettingsActions from '@/containers/Settings/withSettingsActions';
|
|||||||
|
|
||||||
import { compose } from '@/utils';
|
import { compose } from '@/utils';
|
||||||
import {
|
import {
|
||||||
useDisconnectBankAccount,
|
|
||||||
useUpdateBankAccount,
|
useUpdateBankAccount,
|
||||||
useExcludeUncategorizedTransactions,
|
useExcludeUncategorizedTransactions,
|
||||||
useUnexcludeUncategorizedTransactions,
|
useUnexcludeUncategorizedTransactions,
|
||||||
} from '@/hooks/query/bank-rules';
|
} from '@/hooks/query/bank-rules';
|
||||||
import { withBanking } from '../withBanking';
|
import { withBanking } from '../withBanking';
|
||||||
|
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||||
|
import { DialogsName } from '@/constants/dialogs';
|
||||||
|
|
||||||
function AccountTransactionsActionsBar({
|
function AccountTransactionsActionsBar({
|
||||||
// #withDialogActions
|
// #withDialogActions
|
||||||
@@ -60,6 +61,9 @@ function AccountTransactionsActionsBar({
|
|||||||
// #withBanking
|
// #withBanking
|
||||||
uncategorizedTransationsIdsSelected,
|
uncategorizedTransationsIdsSelected,
|
||||||
excludedTransactionsIdsSelected,
|
excludedTransactionsIdsSelected,
|
||||||
|
|
||||||
|
// #withAlerts
|
||||||
|
openAlert,
|
||||||
}) {
|
}) {
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { accountId, currentAccount } = useAccountTransactionsContext();
|
const { accountId, currentAccount } = useAccountTransactionsContext();
|
||||||
@@ -67,7 +71,6 @@ function AccountTransactionsActionsBar({
|
|||||||
// Refresh cashflow infinity transactions hook.
|
// Refresh cashflow infinity transactions hook.
|
||||||
const { refresh } = useRefreshCashflowTransactionsInfinity();
|
const { refresh } = useRefreshCashflowTransactionsInfinity();
|
||||||
|
|
||||||
const { mutateAsync: disconnectBankAccount } = useDisconnectBankAccount();
|
|
||||||
const { mutateAsync: updateBankAccount } = useUpdateBankAccount();
|
const { mutateAsync: updateBankAccount } = useUpdateBankAccount();
|
||||||
|
|
||||||
// Retrieves the money in/out buttons options.
|
// Retrieves the money in/out buttons options.
|
||||||
@@ -75,6 +78,7 @@ function AccountTransactionsActionsBar({
|
|||||||
const addMoneyOutOptions = useMemo(() => getAddMoneyOutOptions(), []);
|
const addMoneyOutOptions = useMemo(() => getAddMoneyOutOptions(), []);
|
||||||
|
|
||||||
const isFeedsActive = !!currentAccount.is_feeds_active;
|
const isFeedsActive = !!currentAccount.is_feeds_active;
|
||||||
|
const isFeedsPaused = currentAccount.is_feeds_paused;
|
||||||
const isSyncingOwner = currentAccount.is_syncing_owner;
|
const isSyncingOwner = currentAccount.is_syncing_owner;
|
||||||
|
|
||||||
// Handle table row size change.
|
// Handle table row size change.
|
||||||
@@ -108,19 +112,9 @@ function AccountTransactionsActionsBar({
|
|||||||
|
|
||||||
// Handles the bank account disconnect click.
|
// Handles the bank account disconnect click.
|
||||||
const handleDisconnectClick = () => {
|
const handleDisconnectClick = () => {
|
||||||
disconnectBankAccount({ bankAccountId: accountId })
|
openDialog(DialogsName.DisconnectBankAccountConfirmation, {
|
||||||
.then(() => {
|
bankAccountId: accountId,
|
||||||
AppToaster.show({
|
});
|
||||||
message: 'The bank account has been disconnected.',
|
|
||||||
intent: Intent.SUCCESS,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
AppToaster.show({
|
|
||||||
message: 'Something went wrong.',
|
|
||||||
intent: Intent.DANGER,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
// handles the bank update button click.
|
// handles the bank update button click.
|
||||||
const handleBankUpdateClick = () => {
|
const handleBankUpdateClick = () => {
|
||||||
@@ -191,6 +185,19 @@ function AccountTransactionsActionsBar({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle resume bank feeds syncing.
|
||||||
|
const handleResumeFeedsSyncing = () => {
|
||||||
|
openAlert('resume-feeds-syncing-bank-accounnt', {
|
||||||
|
bankAccountId: accountId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Handles pause bank feeds syncing.
|
||||||
|
const handlePauseFeedsSyncing = () => {
|
||||||
|
openAlert('pause-feeds-syncing-bank-accounnt', {
|
||||||
|
bankAccountId: accountId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardActionsBar>
|
<DashboardActionsBar>
|
||||||
<NavbarGroup>
|
<NavbarGroup>
|
||||||
@@ -238,7 +245,9 @@ function AccountTransactionsActionsBar({
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
content={
|
content={
|
||||||
isFeedsActive
|
isFeedsActive
|
||||||
? 'The bank syncing is active'
|
? isFeedsPaused
|
||||||
|
? 'The bank syncing is paused'
|
||||||
|
: 'The bank syncing is active'
|
||||||
: 'The bank syncing is disconnected'
|
: 'The bank syncing is disconnected'
|
||||||
}
|
}
|
||||||
minimal={true}
|
minimal={true}
|
||||||
@@ -247,7 +256,13 @@ function AccountTransactionsActionsBar({
|
|||||||
<Button
|
<Button
|
||||||
className={Classes.MINIMAL}
|
className={Classes.MINIMAL}
|
||||||
icon={<Icon icon="feed" iconSize={16} />}
|
icon={<Icon icon="feed" iconSize={16} />}
|
||||||
intent={isFeedsActive ? Intent.SUCCESS : Intent.DANGER}
|
intent={
|
||||||
|
isFeedsActive
|
||||||
|
? isFeedsPaused
|
||||||
|
? Intent.WARNING
|
||||||
|
: Intent.SUCCESS
|
||||||
|
: Intent.DANGER
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</If>
|
</If>
|
||||||
@@ -288,6 +303,23 @@ function AccountTransactionsActionsBar({
|
|||||||
<MenuItem onClick={handleBankUpdateClick} text={'Update'} />
|
<MenuItem onClick={handleBankUpdateClick} text={'Update'} />
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
</If>
|
</If>
|
||||||
|
|
||||||
|
<If condition={isSyncingOwner && isFeedsActive && !isFeedsPaused}>
|
||||||
|
<MenuItem
|
||||||
|
onClick={handlePauseFeedsSyncing}
|
||||||
|
text={'Pause bank feeds'}
|
||||||
|
/>
|
||||||
|
<MenuDivider />
|
||||||
|
</If>
|
||||||
|
|
||||||
|
<If condition={isSyncingOwner && isFeedsActive && isFeedsPaused}>
|
||||||
|
<MenuItem
|
||||||
|
onClick={handleResumeFeedsSyncing}
|
||||||
|
text={'Resume bank feeds'}
|
||||||
|
/>
|
||||||
|
<MenuDivider />
|
||||||
|
</If>
|
||||||
|
|
||||||
<MenuItem onClick={handleBankRulesClick} text={'Bank rules'} />
|
<MenuItem onClick={handleBankRulesClick} text={'Bank rules'} />
|
||||||
|
|
||||||
<If condition={isSyncingOwner && isFeedsActive}>
|
<If condition={isSyncingOwner && isFeedsActive}>
|
||||||
@@ -311,6 +343,7 @@ function AccountTransactionsActionsBar({
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
withDialogActions,
|
withDialogActions,
|
||||||
|
withAlertActions,
|
||||||
withSettingsActions,
|
withSettingsActions,
|
||||||
withSettings(({ cashflowTransactionsSettings }) => ({
|
withSettings(({ cashflowTransactionsSettings }) => ({
|
||||||
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||||
|
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||||
|
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||||
|
|
||||||
|
import { usePauseFeedsBankAccount } from '@/hooks/query/bank-accounts';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause feeds of the bank account alert.
|
||||||
|
*/
|
||||||
|
function PauseFeedsBankAccountAlert({
|
||||||
|
name,
|
||||||
|
|
||||||
|
// #withAlertStoreConnect
|
||||||
|
isOpen,
|
||||||
|
payload: { bankAccountId },
|
||||||
|
|
||||||
|
// #withAlertActions
|
||||||
|
closeAlert,
|
||||||
|
}) {
|
||||||
|
const { mutateAsync: pauseBankAccountFeeds, isLoading } =
|
||||||
|
usePauseFeedsBankAccount();
|
||||||
|
|
||||||
|
// Handle activate item alert cancel.
|
||||||
|
const handleCancelActivateItem = () => {
|
||||||
|
closeAlert(name);
|
||||||
|
};
|
||||||
|
// Handle confirm item activated.
|
||||||
|
const handleConfirmItemActivate = () => {
|
||||||
|
pauseBankAccountFeeds({ bankAccountId })
|
||||||
|
.then(() => {
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'The bank feeds of the bank account has been paused.',
|
||||||
|
intent: Intent.SUCCESS,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {})
|
||||||
|
.finally(() => {
|
||||||
|
closeAlert(name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
cancelButtonText={<T id={'cancel'} />}
|
||||||
|
confirmButtonText={'Pause bank feeds'}
|
||||||
|
intent={Intent.WARNING}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onCancel={handleCancelActivateItem}
|
||||||
|
loading={isLoading}
|
||||||
|
onConfirm={handleConfirmItemActivate}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Are you sure want to pause bank feeds syncing of this bank account, you
|
||||||
|
can always resume it again?
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withAlertStoreConnect(),
|
||||||
|
withAlertActions,
|
||||||
|
)(PauseFeedsBankAccountAlert);
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
|
|
||||||
|
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||||
|
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||||
|
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||||
|
|
||||||
|
import { useResumeFeedsBankAccount } from '@/hooks/query/bank-accounts';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resume bank account feeds alert.
|
||||||
|
*/
|
||||||
|
function ResumeFeedsBankAccountAlert({
|
||||||
|
name,
|
||||||
|
|
||||||
|
// #withAlertStoreConnect
|
||||||
|
isOpen,
|
||||||
|
payload: { bankAccountId },
|
||||||
|
|
||||||
|
// #withAlertActions
|
||||||
|
closeAlert,
|
||||||
|
}) {
|
||||||
|
const { mutateAsync: resumeFeedsBankAccount, isLoading } =
|
||||||
|
useResumeFeedsBankAccount();
|
||||||
|
|
||||||
|
// Handle activate item alert cancel.
|
||||||
|
const handleCancelActivateItem = () => {
|
||||||
|
closeAlert(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle confirm item activated.
|
||||||
|
const handleConfirmItemActivate = () => {
|
||||||
|
resumeFeedsBankAccount({ bankAccountId })
|
||||||
|
.then(() => {
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'The bank feeds of the bank account has been resumed.',
|
||||||
|
intent: Intent.SUCCESS,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {})
|
||||||
|
.finally(() => {
|
||||||
|
closeAlert(name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
cancelButtonText={<T id={'cancel'} />}
|
||||||
|
confirmButtonText={'Resume bank feeds'}
|
||||||
|
intent={Intent.SUCCESS}
|
||||||
|
isOpen={isOpen}
|
||||||
|
onCancel={handleCancelActivateItem}
|
||||||
|
loading={isLoading}
|
||||||
|
onConfirm={handleConfirmItemActivate}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
Are you sure want to resume bank feeds syncing of this bank account, you
|
||||||
|
can always pause it again?
|
||||||
|
</p>
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
withAlertStoreConnect(),
|
||||||
|
withAlertActions,
|
||||||
|
)(ResumeFeedsBankAccountAlert);
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const ResumeFeedsBankAccountAlert = React.lazy(
|
||||||
|
() => import('./ResumeFeedsBankAccount'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const PauseFeedsBankAccountAlert = React.lazy(
|
||||||
|
() => import('./PauseFeedsBankAccount'),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bank account alerts.
|
||||||
|
*/
|
||||||
|
export const BankAccountAlerts = [
|
||||||
|
{
|
||||||
|
name: 'resume-feeds-syncing-bank-accounnt',
|
||||||
|
component: ResumeFeedsBankAccountAlert,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pause-feeds-syncing-bank-accounnt',
|
||||||
|
component: PauseFeedsBankAccountAlert,
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import { Dialog, DialogSuspense } from '@/components';
|
||||||
|
import withDialogRedux from '@/components/DialogReduxConnect';
|
||||||
|
import { compose } from '@/utils';
|
||||||
|
|
||||||
|
const DisconnectBankAccountDialogContent = React.lazy(
|
||||||
|
() => import('./DisconnectBankAccountDialogContent'),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect bank account confirmation dialog.
|
||||||
|
*/
|
||||||
|
function DisconnectBankAccountDialogRoot({
|
||||||
|
dialogName,
|
||||||
|
payload: { bankAccountId },
|
||||||
|
isOpen,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
name={dialogName}
|
||||||
|
title={'Disconnect Bank Account'}
|
||||||
|
isOpen={isOpen}
|
||||||
|
canEscapeJeyClose={true}
|
||||||
|
autoFocus={true}
|
||||||
|
style={{ width: 400 }}
|
||||||
|
>
|
||||||
|
<DialogSuspense>
|
||||||
|
<DisconnectBankAccountDialogContent
|
||||||
|
dialogName={dialogName}
|
||||||
|
bankAccountId={bankAccountId}
|
||||||
|
/>
|
||||||
|
</DialogSuspense>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DisconnectBankAccountDialog = compose(withDialogRedux())(
|
||||||
|
DisconnectBankAccountDialogRoot,
|
||||||
|
);
|
||||||
|
|
||||||
|
DisconnectBankAccountDialog.displayName = 'DisconnectBankAccountDialog';
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import * as Yup from 'yup';
|
||||||
|
import { Button, Intent, Classes } from '@blueprintjs/core';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import { Form, Formik, FormikHelpers } from 'formik';
|
||||||
|
import { AppToaster, FFormGroup, FInputGroup } from '@/components';
|
||||||
|
import { useDisconnectBankAccount } from '@/hooks/query/bank-rules';
|
||||||
|
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||||
|
import { DialogsName } from '@/constants/dialogs';
|
||||||
|
|
||||||
|
interface DisconnectFormValues {
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
label: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const Schema = Yup.object().shape({
|
||||||
|
label: Yup.string().required().label('Confirmation'),
|
||||||
|
});
|
||||||
|
|
||||||
|
interface DisconnectBankAccountDialogContentProps {
|
||||||
|
bankAccountId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DisconnectBankAccountDialogContent({
|
||||||
|
bankAccountId,
|
||||||
|
|
||||||
|
// #withDialogActions
|
||||||
|
closeDialog,
|
||||||
|
}: DisconnectBankAccountDialogContentProps) {
|
||||||
|
const { mutateAsync: disconnectBankAccount } = useDisconnectBankAccount();
|
||||||
|
|
||||||
|
const handleSubmit = (
|
||||||
|
values: DisconnectFormValues,
|
||||||
|
{ setErrors, setSubmitting }: FormikHelpers<DisconnectFormValues>,
|
||||||
|
) => {
|
||||||
|
debugger;
|
||||||
|
setSubmitting(true);
|
||||||
|
|
||||||
|
if (values.label !== 'DISCONNECT ACCOUNT') {
|
||||||
|
setErrors({
|
||||||
|
label: 'The entered value is incorrect.',
|
||||||
|
});
|
||||||
|
setSubmitting(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
disconnectBankAccount({ bankAccountId })
|
||||||
|
.then(() => {
|
||||||
|
setSubmitting(false);
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'The bank account has been disconnected.',
|
||||||
|
intent: Intent.SUCCESS,
|
||||||
|
});
|
||||||
|
closeDialog(DialogsName.DisconnectBankAccountConfirmation);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
setSubmitting(false);
|
||||||
|
AppToaster.show({
|
||||||
|
message: 'Something went wrong.',
|
||||||
|
intent: Intent.DANGER,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancelBtnClick = () => {
|
||||||
|
closeDialog(DialogsName.DisconnectBankAccountConfirmation);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
validationSchema={Schema}
|
||||||
|
initialValues={initialValues}
|
||||||
|
>
|
||||||
|
<Form>
|
||||||
|
<div className={Classes.DIALOG_BODY}>
|
||||||
|
<FFormGroup
|
||||||
|
label={`Type "DISCONNECT ACCOUNT"`}
|
||||||
|
name={'label'}
|
||||||
|
fastField
|
||||||
|
>
|
||||||
|
<FInputGroup name={'label'} fastField />
|
||||||
|
</FFormGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={Classes.DIALOG_FOOTER}>
|
||||||
|
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||||
|
<Button type="submit" intent={Intent.DANGER}>
|
||||||
|
Disconnect Bank Account
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button intent={Intent.NONE} onClick={handleCancelBtnClick}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default R.compose(withDialogActions)(DisconnectBankAccountDialogContent);
|
||||||
91
packages/webapp/src/hooks/query/bank-accounts.ts
Normal file
91
packages/webapp/src/hooks/query/bank-accounts.ts
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import {
|
||||||
|
UseMutationOptions,
|
||||||
|
UseMutationResult,
|
||||||
|
useQueryClient,
|
||||||
|
useMutation,
|
||||||
|
} from 'react-query';
|
||||||
|
import useApiRequest from '../useRequest';
|
||||||
|
import t from './types';
|
||||||
|
|
||||||
|
type PuaseFeedsBankAccountValues = { bankAccountId: number };
|
||||||
|
|
||||||
|
interface PuaseFeedsBankAccountResponse {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes the feeds syncing of the bank account.
|
||||||
|
* @param {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>} options
|
||||||
|
* @returns {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>}
|
||||||
|
*/
|
||||||
|
export function usePauseFeedsBankAccount(
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
PuaseFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
PuaseFeedsBankAccountValues
|
||||||
|
>,
|
||||||
|
): UseMutationResult<
|
||||||
|
PuaseFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
PuaseFeedsBankAccountValues
|
||||||
|
> {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
|
return useMutation<
|
||||||
|
PuaseFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
PuaseFeedsBankAccountValues
|
||||||
|
>(
|
||||||
|
(values) =>
|
||||||
|
apiRequest.post(
|
||||||
|
`/banking/bank_accounts/${values.bankAccountId}/pause_feeds`,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
onSuccess: (res, values) => {
|
||||||
|
queryClient.invalidateQueries([t.ACCOUNT, values.bankAccountId]);
|
||||||
|
},
|
||||||
|
...options,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResumeFeedsBankAccountValues = { bankAccountId: number };
|
||||||
|
|
||||||
|
interface ResumeFeedsBankAccountResponse {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes the feeds syncing of the bank account.
|
||||||
|
* @param {UseMutationResult<ResumeFeedsBankAccountResponse, Error, ResumeFeedsBankAccountValues>} options
|
||||||
|
* @returns {UseMutationResult<ResumeFeedsBankAccountResponse, Error, ResumeFeedsBankAccountValues>}
|
||||||
|
*/
|
||||||
|
export function useResumeFeedsBankAccount(
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
ResumeFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
ResumeFeedsBankAccountValues
|
||||||
|
>,
|
||||||
|
): UseMutationResult<
|
||||||
|
ResumeFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
ResumeFeedsBankAccountValues
|
||||||
|
> {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
|
return useMutation<
|
||||||
|
ResumeFeedsBankAccountResponse,
|
||||||
|
Error,
|
||||||
|
ResumeFeedsBankAccountValues
|
||||||
|
>(
|
||||||
|
(values) =>
|
||||||
|
apiRequest.post(
|
||||||
|
`/banking/bank_accounts/${values.bankAccountId}/resume_feeds`,
|
||||||
|
),
|
||||||
|
{
|
||||||
|
onSuccess: (res, values) => {
|
||||||
|
queryClient.invalidateQueries([t.ACCOUNT, values.bankAccountId]);
|
||||||
|
},
|
||||||
|
...options,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -229,6 +229,9 @@ $dashboard-views-bar-height: 44px;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.#{$ns}-minimal.#{$ns}-intent-warning{
|
||||||
|
color: #cc7e25;
|
||||||
|
}
|
||||||
|
|
||||||
&.button--blue-highlight {
|
&.button--blue-highlight {
|
||||||
background-color: #ebfaff;
|
background-color: #ebfaff;
|
||||||
|
|||||||
Reference in New Issue
Block a user