mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 05:10:31 +00:00
feat: matching uncategorized transactions
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { NextFunction, Request, Response, Router } from 'express';
|
||||
import BaseController from '@/api/controllers/BaseController';
|
||||
import { MatchBankTransactionsApplication } from '@/services/Banking/Matching/MatchBankTransactionsApplication';
|
||||
import { param } from 'express-validator';
|
||||
import {
|
||||
GetMatchedTransactionsFilter,
|
||||
IMatchTransactionDTO,
|
||||
} from '@/services/Banking/Matching/types';
|
||||
|
||||
@Service()
|
||||
export class BankTransactionsMatchingController extends BaseController {
|
||||
@Inject()
|
||||
private bankTransactionsMatchingApp: MatchBankTransactionsApplication;
|
||||
|
||||
/**
|
||||
* Router constructor.
|
||||
*/
|
||||
public router() {
|
||||
const router = Router();
|
||||
|
||||
router.post(
|
||||
'/:transactionId',
|
||||
[param('transactionId').exists()],
|
||||
this.validationResult,
|
||||
this.matchBankTransaction.bind(this)
|
||||
);
|
||||
router.post(
|
||||
'/unmatch/:transactionId',
|
||||
[param('transactionId').exists()],
|
||||
this.validationResult,
|
||||
this.unmatchMatchedBankTransaction.bind(this)
|
||||
);
|
||||
router.get('/', this.getMatchedTransactions.bind(this));
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the given bank transaction.
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
* @returns
|
||||
*/
|
||||
private async matchBankTransaction(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const { tenantId } = req;
|
||||
const { transactionId } = req.params;
|
||||
const matchTransactionDTO = this.matchedBodyData(
|
||||
req
|
||||
) as IMatchTransactionDTO;
|
||||
|
||||
try {
|
||||
await this.bankTransactionsMatchingApp.matchTransaction(
|
||||
tenantId,
|
||||
transactionId,
|
||||
matchTransactionDTO
|
||||
);
|
||||
|
||||
return res.status(200).send({
|
||||
message: 'The bank transaction has been matched.',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
* @returns
|
||||
*/
|
||||
private async unmatchMatchedBankTransaction(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const { tenantId } = req;
|
||||
const transactionId = req.params?.transactionId;
|
||||
|
||||
try {
|
||||
await this.bankTransactionsMatchingApp.unmatchMatchedTransaction(
|
||||
tenantId,
|
||||
transactionId
|
||||
);
|
||||
|
||||
return res.status(200).send({
|
||||
message: 'The bank matched transaction has been unmatched.',
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the matched transactions.
|
||||
* @param {Request} req
|
||||
* @param {Response} res
|
||||
* @param {NextFunction} next
|
||||
*/
|
||||
private async getMatchedTransactions(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const { tenantId } = req;
|
||||
const filter = this.matchedQueryData(req) as GetMatchedTransactionsFilter;
|
||||
|
||||
console.log('test');
|
||||
|
||||
try {
|
||||
const matchedTransactions =
|
||||
await this.bankTransactionsMatchingApp.getMatchedTransactions(
|
||||
tenantId,
|
||||
filter
|
||||
);
|
||||
|
||||
return res.status(200).send({ data: matchedTransactions });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Router } from 'express';
|
||||
import BaseController from '@/api/controllers/BaseController';
|
||||
import { PlaidBankingController } from './PlaidBankingController';
|
||||
import { BankingRulesController } from './BankingRulesController';
|
||||
import { BankTransactionsMatchingController } from './BankTransactionsMatchingController';
|
||||
|
||||
@Service()
|
||||
export class BankingController extends BaseController {
|
||||
@@ -14,6 +15,10 @@ export class BankingController extends BaseController {
|
||||
|
||||
router.use('/plaid', Container.get(PlaidBankingController).router());
|
||||
router.use('/rules', Container.get(BankingRulesController).router());
|
||||
router.use(
|
||||
'/matches',
|
||||
Container.get(BankTransactionsMatchingController).router()
|
||||
);
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
exports.up = function (knex) {
|
||||
return knex.schema.createTable('matched_bank_transactions', (table) => {
|
||||
table.increments('id');
|
||||
table.integer('uncategorized_transaction_id').unsigned();
|
||||
table.string('reference_type');
|
||||
table.integer('reference_id');
|
||||
table.decimal('amount');
|
||||
table.timestamps();
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = function (knex) {
|
||||
return knex.schema.dropTableIfExists('matched_bank_transactions');
|
||||
};
|
||||
@@ -67,6 +67,7 @@ import DocumentLink from '@/models/DocumentLink';
|
||||
import { BankRule } from '@/models/BankRule';
|
||||
import { BankRuleCondition } from '@/models/BankRuleCondition';
|
||||
import { RecognizedBankTransaction } from '@/models/RecognizedBankTransaction';
|
||||
import { MatchedBankTransaction } from '@/models/MatchedBankTransaction';
|
||||
|
||||
export default (knex) => {
|
||||
const models = {
|
||||
@@ -137,6 +138,7 @@ export default (knex) => {
|
||||
BankRule,
|
||||
BankRuleCondition,
|
||||
RecognizedBankTransaction,
|
||||
MatchedBankTransaction,
|
||||
};
|
||||
return mapValues(models, (model) => model.bindKnex(knex));
|
||||
};
|
||||
|
||||
24
packages/server/src/models/MatchedBankTransaction.ts
Normal file
24
packages/server/src/models/MatchedBankTransaction.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import TenantModel from 'models/TenantModel';
|
||||
|
||||
export class MatchedBankTransaction extends TenantModel {
|
||||
/**
|
||||
* Table name.
|
||||
*/
|
||||
static get tableName() {
|
||||
return 'matched_bank_transactions';
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamps columns.
|
||||
*/
|
||||
get timestamps() {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Virtual attributes.
|
||||
*/
|
||||
static get virtualAttributes() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
|
||||
export class GetMatchedTransactionBillsTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale credit note object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['referenceNo'];
|
||||
};
|
||||
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['*'];
|
||||
};
|
||||
|
||||
protected referenceNo(invoice) {
|
||||
return invoice.referenceNo;
|
||||
}
|
||||
|
||||
amount(invoice) {
|
||||
return 1;
|
||||
}
|
||||
amountFormatted() {
|
||||
|
||||
}
|
||||
date() {
|
||||
|
||||
}
|
||||
dateFromatted() {
|
||||
|
||||
}
|
||||
transactionId(invoice) {
|
||||
return invoice.id;
|
||||
}
|
||||
transactionNo() {
|
||||
|
||||
}
|
||||
transactionType() {}
|
||||
transsactionTypeFormatted() {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
|
||||
export class GetMatchedTransactionExpensesTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale credit note object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['referenceNo'];
|
||||
};
|
||||
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['*'];
|
||||
};
|
||||
|
||||
protected referenceNo(invoice) {
|
||||
return invoice.referenceNo;
|
||||
}
|
||||
|
||||
amount(invoice) {
|
||||
return 1;
|
||||
}
|
||||
amountFormatted() {}
|
||||
date() {}
|
||||
dateFromatted() {}
|
||||
transactionId(invoice) {
|
||||
return invoice.id;
|
||||
}
|
||||
transactionNo() {}
|
||||
transactionType() {}
|
||||
transsactionTypeFormatted() {}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
|
||||
export class GetMatchedTransactionInvoicesTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale credit note object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['referenceNo', 'transactionNo'];
|
||||
};
|
||||
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['*'];
|
||||
};
|
||||
|
||||
protected referenceNo(invoice) {
|
||||
return invoice.referenceNo;
|
||||
}
|
||||
|
||||
protected transactionNo(invoice) {
|
||||
return invoice.invoiceNo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Transformer } from '@/lib/Transformer/Transformer';
|
||||
|
||||
export class GetMatchedTransactionManualJournalsTransformer extends Transformer {
|
||||
/**
|
||||
* Include these attributes to sale credit note object.
|
||||
* @returns {Array}
|
||||
*/
|
||||
public includeAttributes = (): string[] => {
|
||||
return ['referenceNo'];
|
||||
};
|
||||
|
||||
public excludeAttributes = (): string[] => {
|
||||
return ['*'];
|
||||
};
|
||||
|
||||
protected referenceNo(invoice) {
|
||||
return invoice.referenceNo;
|
||||
}
|
||||
|
||||
amount(invoice) {
|
||||
return 1;
|
||||
}
|
||||
amountFormatted() {}
|
||||
date() {}
|
||||
dateFromatted() {}
|
||||
transactionId(invoice) {
|
||||
return invoice.id;
|
||||
}
|
||||
transactionNo() {}
|
||||
transactionType() {}
|
||||
transsactionTypeFormatted() {}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import * as R from 'ramda';
|
||||
import { PromisePool } from '@supercharge/promise-pool';
|
||||
import { GetMatchedTransactionsFilter } from './types';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||
import { GetMatchedTransactionInvoicesTransformer } from './GetMatchedTransactionInvoicesTransformer';
|
||||
import { GetMatchedTransactionBillsTransformer } from './GetMatchedTransactionBillsTransformer';
|
||||
import { GetMatchedTransactionExpensesTransformer } from './GetMatchedTransactionExpensesTransformer';
|
||||
import { GetMatchedTransactionManualJournalsTransformer } from './GetMatchedTransactionManualJournalsTransformer';
|
||||
|
||||
@Service()
|
||||
export class GetMatchedTransactions {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private transformer: TransformerInjectable;
|
||||
|
||||
/**
|
||||
* Retrieves the matched transactions.
|
||||
* @param {number} tenantId -
|
||||
* @param {GetMatchedTransactionsFilter} filter -
|
||||
*/
|
||||
public async getMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
const registered = [
|
||||
{
|
||||
type: 'SaleInvoice',
|
||||
callback: this.getSaleInvoicesMatchedTransactions.bind(this),
|
||||
},
|
||||
{
|
||||
type: 'Bill',
|
||||
callback: this.getBillsMatchedTransactions.bind(this),
|
||||
},
|
||||
{
|
||||
type: 'Expense',
|
||||
callback: this.getExpensesMatchedTransactions.bind(this),
|
||||
},
|
||||
{
|
||||
type: 'ManualJournal',
|
||||
callback: this.getManualJournalsMatchedTransactions.bind(this),
|
||||
},
|
||||
];
|
||||
const filtered = filter.transactionType
|
||||
? registered.filter((item) => item.type === filter.transactionType)
|
||||
: registered;
|
||||
|
||||
const matchedTransactions = await PromisePool.withConcurrency(2)
|
||||
.for(filtered)
|
||||
.process(async ({ type, callback }) => {
|
||||
return callback(tenantId, filter);
|
||||
});
|
||||
return R.compose(R.flatten)(matchedTransactions?.results);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} tenantId -
|
||||
* @param {GetMatchedTransactionsFilter} filter -
|
||||
*/
|
||||
async getSaleInvoicesMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
|
||||
const invoices = await SaleInvoice.query();
|
||||
|
||||
return this.transformer.transform(
|
||||
tenantId,
|
||||
invoices,
|
||||
new GetMatchedTransactionInvoicesTransformer()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} tenantId -
|
||||
* @param {GetMatchedTransactionsFilter} filter -
|
||||
*/
|
||||
async getBillsMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
const { Bill } = this.tenancy.models(tenantId);
|
||||
|
||||
const bills = await Bill.query();
|
||||
|
||||
return this.transformer.transform(
|
||||
tenantId,
|
||||
bills,
|
||||
new GetMatchedTransactionBillsTransformer()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} tenantId
|
||||
* @param {GetMatchedTransactionsFilter} filter
|
||||
* @returns
|
||||
*/
|
||||
async getExpensesMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
const { Expense } = this.tenancy.models(tenantId);
|
||||
|
||||
const expenses = await Expense.query();
|
||||
|
||||
return this.transformer.transform(
|
||||
tenantId,
|
||||
expenses,
|
||||
new GetMatchedTransactionManualJournalsTransformer()
|
||||
);
|
||||
}
|
||||
|
||||
async getManualJournalsMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
const { ManualJournal } = this.tenancy.models(tenantId);
|
||||
|
||||
const manualJournals = await ManualJournal.query();
|
||||
|
||||
return this.transformer.transform(
|
||||
tenantId,
|
||||
manualJournals,
|
||||
new GetMatchedTransactionManualJournalsTransformer()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
interface MatchedTransaction {
|
||||
amount: number;
|
||||
amountFormatted: string;
|
||||
date: string;
|
||||
dateFormatted: string;
|
||||
referenceNo: string;
|
||||
transactionNo: string;
|
||||
transactionId: number;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { GetMatchedTransactions } from './GetMatchedTransactions';
|
||||
import { MatchBankTransactions } from './MatchTransactions';
|
||||
import { UnmatchMatchedBankTransaction } from './UnmatchMatchedTransaction';
|
||||
import { GetMatchedTransactionsFilter, IMatchTransactionDTO } from './types';
|
||||
|
||||
@Service()
|
||||
export class MatchBankTransactionsApplication {
|
||||
@Inject()
|
||||
private getMatchedTransactionsService: GetMatchedTransactions;
|
||||
|
||||
@Inject()
|
||||
private matchTransactionService: MatchBankTransactions;
|
||||
|
||||
@Inject()
|
||||
private unmatchMatchedTransactionService: UnmatchMatchedBankTransaction;
|
||||
|
||||
/**
|
||||
* Retrieves the matched transactions.
|
||||
* @param {number} tenantId -
|
||||
* @param {GetMatchedTransactionsFilter} filter -
|
||||
* @returns
|
||||
*/
|
||||
public getMatchedTransactions(
|
||||
tenantId: number,
|
||||
filter: GetMatchedTransactionsFilter
|
||||
) {
|
||||
return this.getMatchedTransactionsService.getMatchedTransactions(
|
||||
tenantId,
|
||||
filter
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the given uncategorized transaction with the given system transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} uncategorizedTransactionId
|
||||
* @param {IMatchTransactionDTO} matchTransactionsDTO
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public matchTransaction(
|
||||
tenantId: number,
|
||||
uncategorizedTransactionId: number,
|
||||
matchTransactionsDTO: IMatchTransactionDTO
|
||||
): Promise<void> {
|
||||
return this.matchTransactionService.matchTransaction(
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
matchTransactionsDTO
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmatch the given matched transaction.
|
||||
* @param {number} tenantId
|
||||
* @param {number} uncategorizedTransactionId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public unmatchMatchedTransaction(
|
||||
tenantId: number,
|
||||
uncategorizedTransactionId: number
|
||||
) {
|
||||
return this.unmatchMatchedTransactionService.unmatchMatchedTransaction(
|
||||
tenantId,
|
||||
uncategorizedTransactionId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { PromisePool } from '@supercharge/promise-pool';
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import {
|
||||
IBankTransactionMatchedEventPayload,
|
||||
IBankTransactionMatchingEventPayload,
|
||||
IMatchTransactionDTO,
|
||||
} from './types';
|
||||
|
||||
@Service()
|
||||
export class MatchBankTransactions {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
/**
|
||||
* Matches the given uncategorized transaction to the given references.
|
||||
* @param {number} tenantId
|
||||
* @param {number} uncategorizedTransactionId
|
||||
*/
|
||||
public matchTransaction(
|
||||
tenantId: number,
|
||||
uncategorizedTransactionId: number,
|
||||
matchTransactionsDTO: IMatchTransactionDTO
|
||||
) {
|
||||
const { matchedTransactions } = matchTransactionsDTO;
|
||||
const { MatchBankTransaction } = this.tenancy.models(tenantId);
|
||||
|
||||
//
|
||||
return this.uow.withTransaction(tenantId, async (trx: Knex.Transaction) => {
|
||||
// Triggers the event `onSaleInvoiceCreated`.
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onMatching, {
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
matchTransactionsDTO,
|
||||
trx,
|
||||
} as IBankTransactionMatchingEventPayload);
|
||||
|
||||
//
|
||||
await PromisePool.withConcurrency(10)
|
||||
.for(matchedTransactions)
|
||||
.process(async (matchedTransaction) => {
|
||||
await MatchBankTransaction.query(trx).insert({
|
||||
uncategorizedTransactionId,
|
||||
referenceType: matchedTransaction.referenceType,
|
||||
referenceId: matchedTransaction.referenceId,
|
||||
amount: matchedTransaction.amount,
|
||||
});
|
||||
});
|
||||
|
||||
// Triggers the event `onSaleInvoiceCreated`.
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onMatched, {
|
||||
tenantId,
|
||||
uncategorizedTransactionId,
|
||||
matchTransactionsDTO,
|
||||
trx,
|
||||
} as IBankTransactionMatchedEventPayload);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import UnitOfWork from '@/services/UnitOfWork';
|
||||
import events from '@/subscribers/events';
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { IBankTransactionUnmatchingEventPayload } from './types';
|
||||
|
||||
@Service()
|
||||
export class UnmatchMatchedBankTransaction {
|
||||
@Inject()
|
||||
private tenancy: HasTenancyService;
|
||||
|
||||
@Inject()
|
||||
private uow: UnitOfWork;
|
||||
|
||||
@Inject()
|
||||
private eventPublisher: EventPublisher;
|
||||
|
||||
public unmatchMatchedTransaction(
|
||||
tenantId: number,
|
||||
uncategorizedTransactionId: number
|
||||
) {
|
||||
const { MatchedBankTransaction } = this.tenancy.models(tenantId);
|
||||
|
||||
return this.uow.withTransaction(tenantId, async (trx) => {
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onUnmatching, {
|
||||
tenantId,
|
||||
trx,
|
||||
} as IBankTransactionUnmatchingEventPayload);
|
||||
|
||||
await MatchedBankTransaction.query(trx)
|
||||
.where('uncategorizedTransactionId', uncategorizedTransactionId)
|
||||
.delete();
|
||||
|
||||
await this.eventPublisher.emitAsync(events.bankMatch.onUnmatched, {
|
||||
tenantId,
|
||||
trx,
|
||||
} as IBankTransactionUnmatchingEventPayload);
|
||||
});
|
||||
}
|
||||
}
|
||||
39
packages/server/src/services/Banking/Matching/types.ts
Normal file
39
packages/server/src/services/Banking/Matching/types.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Knex } from 'knex';
|
||||
|
||||
export interface IBankTransactionMatchingEventPayload {
|
||||
tenantId: number;
|
||||
uncategorizedTransactionId: number;
|
||||
matchTransactionsDTO: IMatchTransactionDTO;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IBankTransactionMatchedEventPayload {
|
||||
tenantId: number;
|
||||
uncategorizedTransactionId: number;
|
||||
matchTransactionsDTO: IMatchTransactionDTO;
|
||||
trx?: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface IBankTransactionUnmatchingEventPayload {
|
||||
tenantId: number;
|
||||
}
|
||||
|
||||
export interface IBankTransactionUnmatchedEventPayload {
|
||||
tenantId: number;
|
||||
}
|
||||
|
||||
export interface IMatchTransactionDTO {
|
||||
matchedTransactions: Array<{
|
||||
referenceType: string;
|
||||
referenceId: number;
|
||||
amount: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface GetMatchedTransactionsFilter {
|
||||
fromDate: string;
|
||||
toDate: string;
|
||||
minAmount: number;
|
||||
maxAmount: number;
|
||||
transactionType: string;
|
||||
}
|
||||
@@ -618,6 +618,7 @@ export default {
|
||||
onItemCreated: 'onPlaidItemCreated',
|
||||
},
|
||||
|
||||
// Bank rules.
|
||||
bankRules: {
|
||||
onCreating: 'onBankRuleCreating',
|
||||
onCreated: 'onBankRuleCreated',
|
||||
@@ -628,4 +629,13 @@ export default {
|
||||
onDeleting: 'onBankRuleDeleting',
|
||||
onDeleted: 'onBankRuleDeleted',
|
||||
},
|
||||
|
||||
// Bank matching.
|
||||
bankMatch: {
|
||||
onMatching: 'onBankTransactionMatching',
|
||||
onMatched: 'onBankTransactionMatched',
|
||||
|
||||
onUnmatching: 'onBankTransactionUnmathcing',
|
||||
onUnmatched: 'onBankTransactionUnmathced',
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user