mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 15:50:32 +00:00
feat: recognize the syncd bank transactions
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema.table('uncategorized_cashflow_transactions', (table) => {
|
||||||
|
table.string('batch');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.table('uncategorized_cashflow_transactions', (table) => {
|
||||||
|
table.dropColumn('batch');
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -267,4 +267,5 @@ export interface CreateUncategorizedTransactionDTO {
|
|||||||
description?: string;
|
description?: string;
|
||||||
referenceNo?: string | null;
|
referenceNo?: string | null;
|
||||||
plaidTransactionId?: string | null;
|
plaidTransactionId?: string | null;
|
||||||
|
batch?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
export interface IPlaidItemCreatedEventPayload {
|
export interface IPlaidItemCreatedEventPayload {
|
||||||
tenantId: number;
|
tenantId: number;
|
||||||
plaidAccessToken: string;
|
plaidAccessToken: string;
|
||||||
@@ -54,3 +56,10 @@ export interface SyncAccountsTransactionsTask {
|
|||||||
plaidAccountId: number;
|
plaidAccountId: number;
|
||||||
plaidTransactions: PlaidTransaction[];
|
plaidTransactions: PlaidTransaction[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPlaidTransactionsSyncedEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
plaidAccountId: number;
|
||||||
|
batch: string;
|
||||||
|
trx?: Knex.Transaction
|
||||||
|
}
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ import { ValidateMatchingOnManualJournalDelete } from '@/services/Banking/Matchi
|
|||||||
import { ValidateMatchingOnPaymentReceivedDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnPaymentReceivedDelete';
|
import { ValidateMatchingOnPaymentReceivedDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnPaymentReceivedDelete';
|
||||||
import { ValidateMatchingOnPaymentMadeDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnPaymentMadeDelete';
|
import { ValidateMatchingOnPaymentMadeDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnPaymentMadeDelete';
|
||||||
import { ValidateMatchingOnCashflowDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnCashflowDelete';
|
import { ValidateMatchingOnCashflowDelete } from '@/services/Banking/Matching/events/ValidateMatchingOnCashflowDelete';
|
||||||
|
import { RecognizeSyncedBankTranasctions } from '@/services/Banking/Plaid/subscribers/RecognizeSyncedBankTransactions';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return new EventPublisher();
|
return new EventPublisher();
|
||||||
@@ -262,5 +263,8 @@ export const susbcribers = () => {
|
|||||||
ValidateMatchingOnManualJournalDelete,
|
ValidateMatchingOnManualJournalDelete,
|
||||||
ValidateMatchingOnPaymentReceivedDelete,
|
ValidateMatchingOnPaymentReceivedDelete,
|
||||||
ValidateMatchingOnPaymentMadeDelete,
|
ValidateMatchingOnPaymentMadeDelete,
|
||||||
|
|
||||||
|
// Plaid
|
||||||
|
RecognizeSyncedBankTranasctions,
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Inject, Service } from 'typedi';
|
import { Inject, Service } from 'typedi';
|
||||||
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
|
||||||
import { GetMatchedTransactionsFilter } from './types';
|
import { GetMatchedTransactionsFilter } from './types';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
|
import { GetMatchedTransactionExpensesTransformer } from './GetMatchedTransactionExpensesTransformer';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByType {
|
export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByType {
|
||||||
@@ -14,7 +14,7 @@ export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByTy
|
|||||||
protected transformer: TransformerInjectable;
|
protected transformer: TransformerInjectable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the matched transactions of expenses.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {GetMatchedTransactionsFilter} filter
|
* @param {GetMatchedTransactionsFilter} filter
|
||||||
* @returns
|
* @returns
|
||||||
@@ -25,12 +25,25 @@ export class GetMatchedTransactionsByExpenses extends GetMatchedTransactionsByTy
|
|||||||
) {
|
) {
|
||||||
const { Expense } = this.tenancy.models(tenantId);
|
const { Expense } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const expenses = await Expense.query();
|
const expenses = await Expense.query().onBuild((query) => {
|
||||||
|
query.whereNotExists(Expense.relatedQuery('matchedBankTransaction'));
|
||||||
|
if (filter.fromDate) {
|
||||||
|
query.where('payment_date', '>=', filter.fromDate);
|
||||||
|
}
|
||||||
|
if (filter.toDate) {
|
||||||
|
query.where('payment_date', '<=', filter.toDate);
|
||||||
|
}
|
||||||
|
if (filter.minAmount) {
|
||||||
|
query.where('total_amount', '>=', filter.minAmount);
|
||||||
|
}
|
||||||
|
if (filter.maxAmount) {
|
||||||
|
query.where('total_amount', '<=', filter.maxAmount);
|
||||||
|
}
|
||||||
|
});
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
tenantId,
|
tenantId,
|
||||||
expenses,
|
expenses,
|
||||||
new GetMatchedTransactionManualJournalsTransformer()
|
new GetMatchedTransactionExpensesTransformer()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||||
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
||||||
import { Inject, Service } from 'typedi';
|
|
||||||
import { GetMatchedTransactionsFilter } from './types';
|
|
||||||
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
import { GetMatchedTransactionsByType } from './GetMatchedTransactionsByType';
|
||||||
|
import { GetMatchedTransactionsFilter } from './types';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactionsByType {
|
export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactionsByType {
|
||||||
@@ -17,12 +17,27 @@ export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactio
|
|||||||
*/
|
*/
|
||||||
async getMatchedTransactions(
|
async getMatchedTransactions(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
filter: GetMatchedTransactionsFilter
|
filter: Omit<GetMatchedTransactionsFilter, 'transactionType'>
|
||||||
) {
|
) {
|
||||||
const { ManualJournal } = this.tenancy.models(tenantId);
|
const { ManualJournal } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const manualJournals = await ManualJournal.query();
|
const manualJournals = await ManualJournal.query().onBuild((query) => {
|
||||||
|
query.whereNotExists(
|
||||||
|
ManualJournal.relatedQuery('matchedBankTransaction')
|
||||||
|
);
|
||||||
|
if (filter.fromDate) {
|
||||||
|
query.where('date', '>=', filter.fromDate);
|
||||||
|
}
|
||||||
|
if (filter.toDate) {
|
||||||
|
query.where('date', '<=', filter.toDate);
|
||||||
|
}
|
||||||
|
if (filter.minAmount) {
|
||||||
|
query.where('amount', '>=', filter.minAmount);
|
||||||
|
}
|
||||||
|
if (filter.maxAmount) {
|
||||||
|
query.where('amount', '<=', filter.maxAmount);
|
||||||
|
}
|
||||||
|
});
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
tenantId,
|
tenantId,
|
||||||
manualJournals,
|
manualJournals,
|
||||||
@@ -41,6 +56,7 @@ export class GetMatchedTransactionsByManualJournals extends GetMatchedTransactio
|
|||||||
|
|
||||||
const manualJournal = await ManualJournal.query()
|
const manualJournal = await ManualJournal.query()
|
||||||
.findById(transactionId)
|
.findById(transactionId)
|
||||||
|
.whereNotExists(ManualJournal.relatedQuery('matchedBankTransaction'))
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
return this.transformer.transform(
|
return this.transformer.transform(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
import { IManualJournalDeletingPayload } from '@/interfaces';
|
import { IManualJournalDeletingPayload } from '@/interfaces';
|
||||||
import events from '@/subscribers/events';
|
import events from '@/subscribers/events';
|
||||||
import { ValidateTransactionMatched } from '../ValidateTransactionsMatched';
|
import { ValidateTransactionMatched } from '../ValidateTransactionsMatched';
|
||||||
import { Inject, Service } from 'typedi';
|
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class ValidateMatchingOnCashflowDelete {
|
export class ValidateMatchingOnCashflowDelete {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { entries, groupBy } from 'lodash';
|
|||||||
import { CreateAccount } from '@/services/Accounts/CreateAccount';
|
import { CreateAccount } from '@/services/Accounts/CreateAccount';
|
||||||
import {
|
import {
|
||||||
IAccountCreateDTO,
|
IAccountCreateDTO,
|
||||||
|
\ IPlaidTransactionsSyncedEventPayload,
|
||||||
PlaidAccount,
|
PlaidAccount,
|
||||||
PlaidTransaction,
|
PlaidTransaction,
|
||||||
} from '@/interfaces';
|
} from '@/interfaces';
|
||||||
@@ -16,6 +17,9 @@ import { DeleteCashflowTransaction } from '@/services/Cashflow/DeleteCashflowTra
|
|||||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||||
import { CashflowApplication } from '@/services/Cashflow/CashflowApplication';
|
import { CashflowApplication } from '@/services/Cashflow/CashflowApplication';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
|
import { uniqid } from 'uniqid';
|
||||||
|
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||||
|
import events from '@/subscribers/events';
|
||||||
|
|
||||||
const CONCURRENCY_ASYNC = 10;
|
const CONCURRENCY_ASYNC = 10;
|
||||||
|
|
||||||
@@ -33,6 +37,9 @@ export class PlaidSyncDb {
|
|||||||
@Inject()
|
@Inject()
|
||||||
private deleteCashflowTransactionService: DeleteCashflowTransaction;
|
private deleteCashflowTransactionService: DeleteCashflowTransaction;
|
||||||
|
|
||||||
|
@Inject()
|
||||||
|
private eventPublisher: EventPublisher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs the Plaid bank account.
|
* Syncs the Plaid bank account.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
@@ -92,6 +99,7 @@ export class PlaidSyncDb {
|
|||||||
* @param {number} tenantId - Tenant ID.
|
* @param {number} tenantId - Tenant ID.
|
||||||
* @param {number} plaidAccountId - Plaid account ID.
|
* @param {number} plaidAccountId - Plaid account ID.
|
||||||
* @param {PlaidTransaction[]} plaidTranasctions - Plaid transactions
|
* @param {PlaidTransaction[]} plaidTranasctions - Plaid transactions
|
||||||
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async syncAccountTranactions(
|
public async syncAccountTranactions(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
@@ -101,18 +109,14 @@ export class PlaidSyncDb {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { Account } = this.tenancy.models(tenantId);
|
const { Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
const batch = uniqid();
|
||||||
const cashflowAccount = await Account.query(trx)
|
const cashflowAccount = await Account.query(trx)
|
||||||
.findOne({ plaidAccountId })
|
.findOne({ plaidAccountId })
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
const openingEquityBalance = await Account.query(trx).findOne(
|
|
||||||
'slug',
|
|
||||||
'opening-balance-equity'
|
|
||||||
);
|
|
||||||
// Transformes the Plaid transactions to cashflow create DTOs.
|
// Transformes the Plaid transactions to cashflow create DTOs.
|
||||||
const transformTransaction = transformPlaidTrxsToCashflowCreate(
|
const transformTransaction = transformPlaidTrxsToCashflowCreate(
|
||||||
cashflowAccount.id,
|
cashflowAccount.id
|
||||||
openingEquityBalance.id
|
|
||||||
);
|
);
|
||||||
const uncategorizedTransDTOs =
|
const uncategorizedTransDTOs =
|
||||||
R.map(transformTransaction)(plaidTranasctions);
|
R.map(transformTransaction)(plaidTranasctions);
|
||||||
@@ -123,20 +127,28 @@ export class PlaidSyncDb {
|
|||||||
(uncategoriedDTO) =>
|
(uncategoriedDTO) =>
|
||||||
this.cashflowApp.createUncategorizedTransaction(
|
this.cashflowApp.createUncategorizedTransaction(
|
||||||
tenantId,
|
tenantId,
|
||||||
uncategoriedDTO,
|
{ ...uncategoriedDTO, batch },
|
||||||
trx
|
trx
|
||||||
),
|
),
|
||||||
{ concurrency: 1 }
|
{ concurrency: 1 }
|
||||||
);
|
);
|
||||||
|
// Triggers `onPlaidTransactionsSynced` event.
|
||||||
|
await this.eventPublisher.emitAsync(events.plaid.onTransactionsSynced, {
|
||||||
|
tenantId,
|
||||||
|
plaidAccountId,
|
||||||
|
batch,
|
||||||
|
} as IPlaidTransactionsSyncedEventPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncs the accounts transactions in paraller under controlled concurrency.
|
* Syncs the accounts transactions in paraller under controlled concurrency.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {PlaidTransaction[]} plaidTransactions
|
* @param {PlaidTransaction[]} plaidTransactions
|
||||||
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async syncAccountsTransactions(
|
public async syncAccountsTransactions(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
|
batchNo: string,
|
||||||
plaidAccountsTransactions: PlaidTransaction[],
|
plaidAccountsTransactions: PlaidTransaction[],
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
@@ -149,6 +161,7 @@ export class PlaidSyncDb {
|
|||||||
return this.syncAccountTranactions(
|
return this.syncAccountTranactions(
|
||||||
tenantId,
|
tenantId,
|
||||||
plaidAccountId,
|
plaidAccountId,
|
||||||
|
batchNo,
|
||||||
plaidTransactions,
|
plaidTransactions,
|
||||||
trx
|
trx
|
||||||
);
|
);
|
||||||
@@ -192,13 +205,14 @@ export class PlaidSyncDb {
|
|||||||
* @param {number} tenantId - Tenant ID.
|
* @param {number} tenantId - Tenant ID.
|
||||||
* @param {string} itemId - Plaid item ID.
|
* @param {string} itemId - Plaid item ID.
|
||||||
* @param {string} lastCursor - Last transaction cursor.
|
* @param {string} lastCursor - Last transaction cursor.
|
||||||
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async syncTransactionsCursor(
|
public async syncTransactionsCursor(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
plaidItemId: string,
|
plaidItemId: string,
|
||||||
lastCursor: string,
|
lastCursor: string,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) {
|
): Promise<void> {
|
||||||
const { PlaidItem } = this.tenancy.models(tenantId);
|
const { PlaidItem } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
await PlaidItem.query(trx).findOne({ plaidItemId }).patch({ lastCursor });
|
await PlaidItem.query(trx).findOne({ plaidItemId }).patch({ lastCursor });
|
||||||
@@ -208,12 +222,13 @@ export class PlaidSyncDb {
|
|||||||
* Updates the last feeds updated at of the given Plaid accounts ids.
|
* Updates the last feeds updated at of the given Plaid accounts ids.
|
||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {string[]} plaidAccountIds
|
* @param {string[]} plaidAccountIds
|
||||||
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async updateLastFeedsUpdatedAt(
|
public async updateLastFeedsUpdatedAt(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
plaidAccountIds: string[],
|
plaidAccountIds: string[],
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) {
|
): Promise<void> {
|
||||||
const { Account } = this.tenancy.models(tenantId);
|
const { Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
await Account.query(trx)
|
await Account.query(trx)
|
||||||
@@ -228,13 +243,14 @@ export class PlaidSyncDb {
|
|||||||
* @param {number} tenantId
|
* @param {number} tenantId
|
||||||
* @param {number[]} plaidAccountIds
|
* @param {number[]} plaidAccountIds
|
||||||
* @param {boolean} isFeedsActive
|
* @param {boolean} isFeedsActive
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async updateAccountsFeedsActive(
|
public async updateAccountsFeedsActive(
|
||||||
tenantId: number,
|
tenantId: number,
|
||||||
plaidAccountIds: string[],
|
plaidAccountIds: string[],
|
||||||
isFeedsActive: boolean = true,
|
isFeedsActive: boolean = true,
|
||||||
trx?: Knex.Transaction
|
trx?: Knex.Transaction
|
||||||
) {
|
): Promise<void> {
|
||||||
const { Account } = this.tenancy.models(tenantId);
|
const { Account } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
await Account.query(trx)
|
await Account.query(trx)
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { Inject, Service } from 'typedi';
|
||||||
|
import { EventSubscriber } from '@/lib/EventPublisher/EventPublisher';
|
||||||
|
import {
|
||||||
|
IPlaidItemCreatedEventPayload,
|
||||||
|
IPlaidTransactionsSyncedEventPayload,
|
||||||
|
} from '@/interfaces/Plaid';
|
||||||
|
import events from '@/subscribers/events';
|
||||||
|
import { RecognizeTranasctionsService } from '../../RegonizeTranasctions/RecognizeTranasctionsService';
|
||||||
|
import { runAfterTransaction } from '@/services/UnitOfWork/TransactionsHooks';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export class RecognizeSyncedBankTranasctions extends EventSubscriber {
|
||||||
|
@Inject()
|
||||||
|
private recognizeTranasctionsService: RecognizeTranasctionsService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
*/
|
||||||
|
public attach(bus) {
|
||||||
|
bus.subscribe(
|
||||||
|
events.plaid.onTransactionsSynced,
|
||||||
|
this.handleRecognizeSyncedBankTransactions.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the Plaid item transactions
|
||||||
|
* @param {IPlaidItemCreatedEventPayload} payload - Event payload.
|
||||||
|
*/
|
||||||
|
private handleRecognizeSyncedBankTransactions = async ({
|
||||||
|
tenantId,
|
||||||
|
batch,
|
||||||
|
trx,
|
||||||
|
}: IPlaidTransactionsSyncedEventPayload) => {
|
||||||
|
runAfterTransaction(trx, async () => {
|
||||||
|
await this.recognizeTranasctionsService.recognizeTransactions(
|
||||||
|
tenantId,
|
||||||
|
batch
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -50,14 +50,21 @@ export class RecognizeTranasctionsService {
|
|||||||
* @param {number} tenantId -
|
* @param {number} tenantId -
|
||||||
* @param {Knex.Transaction} trx -
|
* @param {Knex.Transaction} trx -
|
||||||
*/
|
*/
|
||||||
public async recognizeTransactions(tenantId: number, trx?: Knex.Transaction) {
|
public async recognizeTransactions(
|
||||||
|
tenantId: number,
|
||||||
|
batch: string = '',
|
||||||
|
trx?: Knex.Transaction
|
||||||
|
) {
|
||||||
const { UncategorizedCashflowTransaction, BankRule } =
|
const { UncategorizedCashflowTransaction, BankRule } =
|
||||||
this.tenancy.models(tenantId);
|
this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const uncategorizedTranasctions =
|
const uncategorizedTranasctions =
|
||||||
await UncategorizedCashflowTransaction.query()
|
await UncategorizedCashflowTransaction.query().onBuild((query) => {
|
||||||
.where('recognized_transaction_id', null)
|
query.where('recognized_transaction_id', null);
|
||||||
.where('categorized', false);
|
query.where('categorized', false);
|
||||||
|
|
||||||
|
if (batch) query.where('batch', batch);
|
||||||
|
});
|
||||||
|
|
||||||
const bankRules = await BankRule.query().withGraphFetched('conditions');
|
const bankRules = await BankRule.query().withGraphFetched('conditions');
|
||||||
const bankRulesByAccountId = transformToMapBy(
|
const bankRulesByAccountId = transformToMapBy(
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export class DeleteBankRuleSerivce {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async deleteBankRule(tenantId: number, ruleId: number): Promise<void> {
|
public async deleteBankRule(tenantId: number, ruleId: number): Promise<void> {
|
||||||
const { BankRule } = this.tenancy.models(tenantId);
|
const { BankRule, BankRuleCondition } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
const oldBankRule = await BankRule.query()
|
const oldBankRule = await BankRule.query()
|
||||||
.findById(ruleId)
|
.findById(ruleId)
|
||||||
@@ -42,6 +42,7 @@ export class DeleteBankRuleSerivce {
|
|||||||
trx,
|
trx,
|
||||||
} as IBankRuleEventDeletingPayload);
|
} as IBankRuleEventDeletingPayload);
|
||||||
|
|
||||||
|
await BankRuleCondition.query(trx).where('ruleId', ruleId).delete();
|
||||||
await BankRule.query(trx).findById(ruleId).delete();
|
await BankRule.query(trx).findById(ruleId).delete();
|
||||||
|
|
||||||
// Triggers `onBankRuleDeleted` event.
|
// Triggers `onBankRuleDeleted` event.
|
||||||
|
|||||||
@@ -616,6 +616,7 @@ export default {
|
|||||||
|
|
||||||
plaid: {
|
plaid: {
|
||||||
onItemCreated: 'onPlaidItemCreated',
|
onItemCreated: 'onPlaidItemCreated',
|
||||||
|
onTransactionsSynced: 'onPlaidTransactionsSynced',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Bank rules.
|
// Bank rules.
|
||||||
@@ -637,5 +638,5 @@ export default {
|
|||||||
|
|
||||||
onUnmatching: 'onBankTransactionUnmathcing',
|
onUnmatching: 'onBankTransactionUnmathcing',
|
||||||
onUnmatched: 'onBankTransactionUnmathced',
|
onUnmatched: 'onBankTransactionUnmathced',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user