mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-24 08:39:49 +00:00
fix: specific account transactions.
fix: specific expense associated expense account graph. fix: specific manual journal associated account and contact graph.
This commit is contained in:
@@ -23,6 +23,14 @@ export default class AccountsController extends BaseController {
|
|||||||
router() {
|
router() {
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
router.get(
|
||||||
|
'/transactions',
|
||||||
|
[
|
||||||
|
query('account_id').optional().isInt().toInt(),
|
||||||
|
],
|
||||||
|
this.asyncMiddleware(this.accountTransactions.bind(this)),
|
||||||
|
this.catchServiceErrors,
|
||||||
|
);
|
||||||
router.post(
|
router.post(
|
||||||
'/:id/activate',
|
'/:id/activate',
|
||||||
[...this.accountParamSchema],
|
[...this.accountParamSchema],
|
||||||
@@ -329,6 +337,28 @@ export default class AccountsController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve accounts transactions list.
|
||||||
|
* @param {Request} req
|
||||||
|
* @param {Response} res
|
||||||
|
* @param {NextFunction} next
|
||||||
|
* @returns {Response}
|
||||||
|
*/
|
||||||
|
async accountTransactions(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const { tenantId } = req;
|
||||||
|
const transactionsFilter = this.matchedQueryData(req);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { transactions } = await this.accountsService.getAccountsTransactions(
|
||||||
|
tenantId,
|
||||||
|
transactionsFilter
|
||||||
|
);
|
||||||
|
return res.status(200).send({ transactions });
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms service errors to response.
|
* Transforms service errors to response.
|
||||||
* @param {Error}
|
* @param {Error}
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ export interface IAccount {
|
|||||||
accountParentType: string,
|
accountParentType: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface IAccountsTransactionsFilter {
|
||||||
|
accountId?: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAccountTransaction {
|
||||||
|
|
||||||
|
}
|
||||||
export interface IAccountResponse extends IAccount {
|
export interface IAccountResponse extends IAccount {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ export default class AccountTransaction extends TenantModel {
|
|||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const Account = require('models/Account');
|
const Account = require('models/Account');
|
||||||
|
const Contact = require('models/Contact');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account: {
|
account: {
|
||||||
@@ -138,6 +139,14 @@ export default class AccountTransaction extends TenantModel {
|
|||||||
to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
contact: {
|
||||||
|
relation: Model.BelongsToOneRelation,
|
||||||
|
modelClass: Contact.default,
|
||||||
|
join: {
|
||||||
|
from: 'accounts_transactions.contactId',
|
||||||
|
to: 'contacts.id',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export default class ManualJournalEntry extends TenantModel {
|
|||||||
*/
|
*/
|
||||||
static get relationMappings() {
|
static get relationMappings() {
|
||||||
const Account = require('models/Account');
|
const Account = require('models/Account');
|
||||||
|
const Contact = require('models/Contact');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account: {
|
account: {
|
||||||
@@ -31,6 +32,14 @@ export default class ManualJournalEntry extends TenantModel {
|
|||||||
to: 'accounts.id',
|
to: 'accounts.id',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
contact: {
|
||||||
|
relation: Model.BelongsToOneRelation,
|
||||||
|
modelClass: Contact.default,
|
||||||
|
join: {
|
||||||
|
from: 'manual_journals_entries.contactId',
|
||||||
|
to: 'contacts.id',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import {
|
|||||||
IAccount,
|
IAccount,
|
||||||
IAccountsFilter,
|
IAccountsFilter,
|
||||||
IFilterMeta,
|
IFilterMeta,
|
||||||
IAccountResponse
|
IAccountResponse,
|
||||||
|
IAccountsTransactionsFilter,
|
||||||
|
IAccountTransaction
|
||||||
} from 'interfaces';
|
} from 'interfaces';
|
||||||
import {
|
import {
|
||||||
EventDispatcher,
|
EventDispatcher,
|
||||||
@@ -317,7 +319,8 @@ export default class AccountsService {
|
|||||||
* @param {number} accountId
|
* @param {number} accountId
|
||||||
*/
|
*/
|
||||||
public async getAccount(tenantId: number, accountId: number) {
|
public async getAccount(tenantId: number, accountId: number) {
|
||||||
return this.getAccountOrThrowError(tenantId, accountId);
|
const account = await this.getAccountOrThrowError(tenantId, accountId);
|
||||||
|
return this.transformAccountResponse(tenantId, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -628,6 +631,45 @@ export default class AccountsService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts transactions.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @param {IAccountsTransactionsFilter} filter -
|
||||||
|
*/
|
||||||
|
public async getAccountsTransactions(
|
||||||
|
tenantId: number,
|
||||||
|
filter: IAccountsTransactionsFilter,
|
||||||
|
): Promise<{ transactions: IAccountTransaction }> {
|
||||||
|
const { AccountTransaction } = this.tenancy.models(tenantId);
|
||||||
|
|
||||||
|
this.logger.info('[accounts] trying to get accounts transactions list.');
|
||||||
|
const transactions = await AccountTransaction.query().onBuild((query) => {
|
||||||
|
query.orderBy('date', 'DESC');
|
||||||
|
|
||||||
|
if (filter.accountId) {
|
||||||
|
query.where('account_id', filter.accountId);
|
||||||
|
}
|
||||||
|
query.withGraphFetched('account');
|
||||||
|
query.withGraphFetched('contact');
|
||||||
|
});
|
||||||
|
return { transactions };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformes the account model to specific account response.
|
||||||
|
*/
|
||||||
|
private transformAccountResponse(tenantId: number, account: IAccount) {
|
||||||
|
const settings = this.tenancy.settings(tenantId);
|
||||||
|
const baseCurrency = settings.get({
|
||||||
|
group: 'organization',
|
||||||
|
key: 'base_currency',
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...account,
|
||||||
|
currencyCode: baseCurrency,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformes the accounts models to accounts response.
|
* Transformes the accounts models to accounts response.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -641,7 +641,7 @@ export default class ExpensesService implements IExpensesService {
|
|||||||
|
|
||||||
const expense = await expenseRepository.findOneById(expenseId, [
|
const expense = await expenseRepository.findOneById(expenseId, [
|
||||||
'paymentAccount',
|
'paymentAccount',
|
||||||
'categories',
|
'categories.expenseAccount',
|
||||||
]);
|
]);
|
||||||
if (!expense) {
|
if (!expense) {
|
||||||
throw new ServiceError(ERRORS.EXPENSE_NOT_FOUND);
|
throw new ServiceError(ERRORS.EXPENSE_NOT_FOUND);
|
||||||
|
|||||||
@@ -822,7 +822,8 @@ export default class ManualJournalsService implements IManualJournalsService {
|
|||||||
);
|
);
|
||||||
const manualJournal = await ManualJournal.query()
|
const manualJournal = await ManualJournal.query()
|
||||||
.findById(manualJournalId)
|
.findById(manualJournalId)
|
||||||
.withGraphFetched('entries')
|
.withGraphFetched('entries.account')
|
||||||
|
.withGraphFetched('entries.contact')
|
||||||
.withGraphFetched('transactions')
|
.withGraphFetched('transactions')
|
||||||
.withGraphFetched('media');
|
.withGraphFetched('media');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user