@memberjunction/actions-bizapps-accounting
Version:
Accounting system integration actions for MemberJunction
207 lines • 8.6 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { RegisterClass } from '@memberjunction/global';
import { QuickBooksBaseAction } from '../quickbooks-base.action.js';
import { BaseAction } from '@memberjunction/actions';
/**
* Action to retrieve account balances (trial balance) from QuickBooks Online
*/
let GetQuickBooksAccountBalancesAction = class GetQuickBooksAccountBalancesAction extends QuickBooksBaseAction {
/**
* Description of the action
*/
get Description() {
return 'Retrieves account balances (trial balance) from QuickBooks Online for a specific date';
}
/**
* Main execution method
*/
async InternalRunAction(params) {
try {
const contextUser = params.ContextUser;
if (!contextUser) {
throw new Error('Context user is required for QuickBooks API calls');
}
// Store params for use in other methods
this._params = params.Params;
const asOfDate = this.getParamValue(params.Params, 'AsOfDate') ? new Date(this.getParamValue(params.Params, 'AsOfDate')) : new Date();
// QuickBooks doesn't have a direct trial balance API, so we need to:
// 1. Get all accounts
// 2. Get balance for each account as of the specified date
// First, get all accounts
const accounts = await this.getAccounts(params.Params, contextUser);
// Get balances for each account
const accountBalances = [];
for (const account of accounts) {
// For performance, we'll use the current balance from the account
// In a production system, you might want to use the Reports API for historical balances
const balance = {
accountId: account.Id,
accountCode: account.AcctNum || account.Id,
accountName: account.Name,
accountType: this.mapAccountType(account.AccountType),
accountSubType: account.AccountSubType,
normalBalance: this.determineNormalBalance(account.Classification),
currentBalance: account.CurrentBalance || 0,
balanceWithSubAccounts: account.CurrentBalanceWithSubAccounts || 0,
currency: account.CurrencyRef?.value || 'USD',
asOfDate: asOfDate,
isActive: account.Active,
level: account.FullyQualifiedName.split(':').length - 1,
parentAccountId: account.ParentRef?.value,
parentAccountName: account.ParentRef?.name
};
// Apply filters
if (!this.getParamValue(params.Params, 'IncludeZeroBalances') && balance.currentBalance === 0) {
continue;
}
accountBalances.push(balance);
}
// Calculate trial balance summary
const summary = this.calculateTrialBalanceSummary(accountBalances, asOfDate);
// If summarize by type is requested
let typeSummary = undefined;
if (this.getParamValue(params.Params, 'SummarizeByType')) {
typeSummary = this.summarizeByAccountType(accountBalances);
}
// Set output parameters
const outputParams = [
{
Name: 'AccountBalances',
Value: accountBalances,
Type: 'Output'
},
{
Name: 'TrialBalanceSummary',
Value: summary,
Type: 'Output'
},
{
Name: 'TypeSummary',
Value: typeSummary,
Type: 'Output'
},
{
Name: 'TotalAccounts',
Value: accountBalances.length,
Type: 'Output'
}
];
return {
Success: true,
ResultCode: 'SUCCESS',
Params: [...params.Params, ...outputParams],
Message: 'Operation completed successfully'
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return {
Success: false,
ResultCode: 'ERROR',
Message: errorMessage,
Params: params.Params
};
}
}
/**
* Get accounts from QuickBooks
*/
async getAccounts(params, contextUser) {
let query = 'SELECT * FROM Account';
const conditions = [];
// Add active filter
if (!this.getParamValue(params, 'IncludeInactive')) {
conditions.push('Active = true');
}
// Add account type filter
if (this.getParamValue(params, 'AccountTypes')) {
const types = this.getParamValue(params, 'AccountTypes').split(',').map((t) => `'${t.trim()}'`);
conditions.push(`AccountType IN (${types.join(',')})`);
}
// Add conditions to query
if (conditions.length > 0) {
query += ' WHERE ' + conditions.join(' AND ');
}
// Add ordering
query += ' ORDER BY AccountType, AcctNum';
// Execute the query
const response = await this.queryQBO(query, contextUser);
return response.QueryResponse?.Account || [];
}
/**
* Calculate trial balance summary
*/
calculateTrialBalanceSummary(balances, asOfDate) {
let totalDebits = 0;
let totalCredits = 0;
balances.forEach(balance => {
if (balance.currentBalance !== 0) {
if (balance.normalBalance === 'Debit') {
if (balance.currentBalance > 0) {
totalDebits += balance.currentBalance;
}
else {
totalCredits += Math.abs(balance.currentBalance);
}
}
else {
if (balance.currentBalance > 0) {
totalCredits += balance.currentBalance;
}
else {
totalDebits += Math.abs(balance.currentBalance);
}
}
}
});
const difference = Math.abs(totalDebits - totalCredits);
return {
totalDebits,
totalCredits,
isBalanced: difference < 0.01, // Allow for minor rounding differences
difference,
asOfDate
};
}
/**
* Summarize balances by account type
*/
summarizeByAccountType(balances) {
const summary = {};
balances.forEach(balance => {
const type = balance.accountType;
if (!summary[type]) {
summary[type] = {
count: 0,
totalBalance: 0,
accounts: []
};
}
summary[type].count++;
summary[type].totalBalance += balance.currentBalance;
summary[type].accounts.push({
id: balance.accountId,
name: balance.accountName,
balance: balance.currentBalance
});
});
return summary;
}
/**
* Determines the normal balance based on account classification
*/
determineNormalBalance(classification) {
const debitClassifications = ['Asset', 'Expense'];
return debitClassifications.includes(classification) ? 'Debit' : 'Credit';
}
};
GetQuickBooksAccountBalancesAction = __decorate([
RegisterClass(BaseAction, 'GetQuickBooksAccountBalancesAction')
], GetQuickBooksAccountBalancesAction);
export { GetQuickBooksAccountBalancesAction };
//# sourceMappingURL=get-account-balances.action.js.map