mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 04:40:32 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { PlaidApi } from 'plaid';
|
||||
import {
|
||||
ERRORS,
|
||||
IBankAccountDisconnectedEventPayload,
|
||||
IBankAccountDisconnectingEventPayload,
|
||||
} from '../types/BankAccounts.types';
|
||||
import { ACCOUNT_TYPE } from '@/constants/accounts';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { PLAID_CLIENT } from '@/modules/Plaid/Plaid.module';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class DisconnectBankAccountService {
|
||||
constructor(
|
||||
private eventPublisher: EventEmitter2,
|
||||
private uow: UnitOfWork,
|
||||
|
||||
@Inject(PLAID_CLIENT) private plaidClient: PlaidApi,
|
||||
@Inject(Account.name)
|
||||
private accountModel: TenantModelProxy<typeof Account>,
|
||||
|
||||
@Inject(PlaidItem.name)
|
||||
private plaidItemModel: TenantModelProxy<typeof PlaidItem>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Disconnects the given bank account.
|
||||
* @param {number} bankAccountId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async disconnectBankAccount(bankAccountId: number) {
|
||||
// Retrieve the bank account or throw not found error.
|
||||
const account = await this.accountModel()
|
||||
.query()
|
||||
.findById(bankAccountId)
|
||||
.whereIn('account_type', [ACCOUNT_TYPE.CASH, ACCOUNT_TYPE.BANK])
|
||||
.withGraphFetched('plaidItem')
|
||||
.throwIfNotFound();
|
||||
|
||||
const oldPlaidItem = account.plaidItem;
|
||||
|
||||
if (!oldPlaidItem) {
|
||||
throw new ServiceError(ERRORS.BANK_ACCOUNT_NOT_CONNECTED);
|
||||
}
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onBankAccountDisconnecting` event.
|
||||
await this.eventPublisher.emitAsync(events.bankAccount.onDisconnecting, {
|
||||
bankAccountId,
|
||||
} as IBankAccountDisconnectingEventPayload);
|
||||
|
||||
// Remove the Plaid item from the system.
|
||||
await this.plaidItemModel()
|
||||
.query(trx)
|
||||
.findById(account.plaidItemId)
|
||||
.delete();
|
||||
|
||||
// Remove the plaid item association to the bank account.
|
||||
await this.accountModel().query(trx).findById(bankAccountId).patch({
|
||||
plaidAccountId: null,
|
||||
plaidItemId: null,
|
||||
isFeedsActive: false,
|
||||
});
|
||||
// Remove the Plaid item.
|
||||
await this.plaidClient.itemRemove({
|
||||
access_token: oldPlaidItem.plaidAccessToken,
|
||||
});
|
||||
// Triggers `onBankAccountDisconnected` event.
|
||||
await this.eventPublisher.emitAsync(events.bankAccount.onDisconnected, {
|
||||
bankAccountId,
|
||||
trx,
|
||||
} as IBankAccountDisconnectedEventPayload);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { ERRORS } from '../types/BankAccounts.types';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class PauseBankAccountFeeds {
|
||||
constructor(
|
||||
@Inject(Account.name)
|
||||
private accountModel: TenantModelProxy<typeof Account>,
|
||||
@Inject(PlaidItem.name)
|
||||
private plaidItemModel: TenantModelProxy<typeof PlaidItem>,
|
||||
|
||||
private uow: UnitOfWork,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Pauses the bank feed syncing of the given bank account.
|
||||
* @param {number} bankAccountId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async pauseBankAccountFeeds(bankAccountId: number) {
|
||||
const oldAccount = await this.accountModel()
|
||||
.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(async (trx: Knex.Transaction) => {
|
||||
await this.plaidItemModel()
|
||||
.query(trx)
|
||||
.findById(oldAccount.plaidItem.id)
|
||||
.patch({
|
||||
pausedAt: new Date(),
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { PlaidApi } from 'plaid';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { PLAID_CLIENT } from '@/modules/Plaid/Plaid.module';
|
||||
import { ERRORS } from '../types/BankAccounts.types';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class RefreshBankAccountService {
|
||||
constructor(
|
||||
@Inject(PLAID_CLIENT) private plaidClient: PlaidApi,
|
||||
@Inject(Account.name)
|
||||
private readonly accountModel: TenantModelProxy<typeof Account>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Asks Plaid to trigger syncing the given bank account.
|
||||
* @param {number} bankAccountId - Bank account identifier.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async refreshBankAccount(bankAccountId: number) {
|
||||
const bankAccount = await this.accountModel()
|
||||
.query()
|
||||
.findById(bankAccountId)
|
||||
.withGraphFetched('plaidItem')
|
||||
.throwIfNotFound();
|
||||
|
||||
// Can't continue if the given account is not linked with Plaid item.
|
||||
if (!bankAccount.plaidItem) {
|
||||
throw new ServiceError(ERRORS.BANK_ACCOUNT_NOT_CONNECTED);
|
||||
}
|
||||
await this.plaidClient.transactionsRefresh({
|
||||
access_token: bankAccount.plaidItem.plaidAccessToken,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { ERRORS } from '../types/BankAccounts.types';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { PlaidItem } from '@/modules/BankingPlaid/models/PlaidItem';
|
||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ResumeBankAccountFeedsService {
|
||||
constructor(
|
||||
@Inject(Account.name)
|
||||
private accountModel: TenantModelProxy<typeof Account>,
|
||||
|
||||
@Inject(PlaidItem.name)
|
||||
private plaidItemModel: TenantModelProxy<typeof PlaidItem>,
|
||||
|
||||
private uow: UnitOfWork,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Resumes the bank feeds syncing of the bank account.
|
||||
* @param {number} bankAccountId
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async resumeBankAccountFeeds(bankAccountId: number) {
|
||||
const oldAccount = await this.accountModel()
|
||||
.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(async (trx: Knex.Transaction) => {
|
||||
await this.plaidItemModel()
|
||||
.query(trx)
|
||||
.findById(oldAccount.plaidItem.id)
|
||||
.patch({
|
||||
pausedAt: null,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user