@memberjunction/actions-bizapps-accounting
Version:
Accounting system integration actions for MemberJunction
172 lines • 7.25 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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuickBooksBaseAction = void 0;
const global_1 = require("@memberjunction/global");
const base_accounting_action_1 = require("../../base/base-accounting-action");
const actions_1 = require("@memberjunction/actions");
/**
* Base class for all QuickBooks Online actions.
* Handles QB-specific authentication and API interaction patterns.
*/
let QuickBooksBaseAction = class QuickBooksBaseAction extends base_accounting_action_1.BaseAccountingAction {
accountingProvider = 'QuickBooks Online';
integrationName = 'QuickBooks Online';
/**
* QuickBooks API version
*/
apiVersion = 'v3';
/**
* QuickBooks minor version for API compatibility
*/
minorVersion = '65'; // Latest as of 2024
/**
* Makes an authenticated request to QuickBooks Online API
*/
async makeQBORequest(endpoint, method = 'GET', body, contextUser) {
if (!contextUser) {
throw new Error('Context user is required for QuickBooks API calls');
}
// Get company ID from action params
const companyId = this.getParamValue(this._params || [], 'CompanyID');
if (!companyId) {
throw new Error('CompanyID parameter is required');
}
// Get the integration credentials
const integration = await this.getCompanyIntegration(companyId, contextUser);
// Get OAuth tokens (from env vars or database)
const { accessToken } = await this.getOAuthTokens(integration);
// Get QuickBooks company ID (realm ID) from ExternalSystemID
const realmId = integration.ExternalSystemID || this.getCredentialFromEnv(companyId, 'REALM_ID');
if (!realmId) {
throw new Error('QuickBooks Realm ID not found. Set in CompanyIntegration.ExternalSystemID or environment variable');
}
// Build the full URL using the environment from integration
const baseUrl = await this.getQuickBooksAPIUrl(integration);
const fullUrl = `${baseUrl}/${this.apiVersion}/company/${realmId}/${endpoint}`;
// Prepare headers
const headers = {
'Authorization': `Bearer ${accessToken}`,
'Accept': 'application/json',
'Content-Type': 'application/json'
};
// Add minor version header for API compatibility
if (this.minorVersion) {
headers['Intuit-Company-ID'] = realmId;
headers['Accept'] = `application/json;minorversion=${this.minorVersion}`;
}
try {
const response = await fetch(fullUrl, {
method,
headers,
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
const errorText = await response.text();
let errorMessage = `QuickBooks API error: ${response.status} ${response.statusText}`;
try {
const errorJson = JSON.parse(errorText);
if (errorJson.Fault && errorJson.Fault.Error) {
const qbError = errorJson.Fault.Error[0];
errorMessage = `QuickBooks API error: ${qbError.Message} (Code: ${qbError.code})`;
}
}
catch {
errorMessage += ` - ${errorText}`;
}
throw new Error(errorMessage);
}
const result = await response.json();
return result;
}
catch (error) {
if (error instanceof Error) {
throw error;
}
throw new Error(`QuickBooks API request failed: ${error}`);
}
}
/**
* Handles QuickBooks query language requests
*/
async queryQBO(query, contextUser) {
const encodedQuery = encodeURIComponent(query);
return this.makeQBORequest(`query?query=${encodedQuery}`, 'GET', undefined, contextUser);
}
/**
* Converts QuickBooks date format to standard ISO format
*/
parseQBODate(qboDate) {
// QuickBooks uses YYYY-MM-DD format
return new Date(qboDate + 'T00:00:00Z');
}
/**
* Formats date for QuickBooks API
*/
formatQBODate(date) {
return date.toISOString().split('T')[0];
}
/**
* Maps QuickBooks account types to standard accounting categories
*/
mapAccountType(qboAccountType) {
const typeMap = {
'Bank': 'Asset',
'Accounts Receivable': 'Asset',
'Other Current Asset': 'Asset',
'Fixed Asset': 'Asset',
'Other Asset': 'Asset',
'Accounts Payable': 'Liability',
'Credit Card': 'Liability',
'Long Term Liability': 'Liability',
'Other Current Liability': 'Liability',
'Equity': 'Equity',
'Income': 'Revenue',
'Other Income': 'Revenue',
'Cost of Goods Sold': 'Expense',
'Expense': 'Expense',
'Other Expense': 'Expense'
};
return typeMap[qboAccountType] || 'Other';
}
/**
* Gets the appropriate QuickBooks API URL based on configuration
*/
async getQuickBooksAPIUrl(integration) {
// First, check if there's a URL in the Integration entity
// The Integration property should be loaded via the view, not accessed as a sub-property
const integrationNavURL = integration.IntegrationNavigationBaseURL;
if (integrationNavURL) {
return integrationNavURL;
}
// Fall back to environment-based URL
const isSandbox = integration.CustomAttribute1?.toLowerCase() === 'sandbox';
return isSandbox
? 'https://sandbox-quickbooks.api.intuit.com'
: 'https://quickbooks.api.intuit.com';
}
/**
* Store the params for use in other methods
*/
_params;
/**
* Override the required abstract method
*/
async InternalRunAction(params) {
// Store params for use in other methods
this._params = params.Params;
// This is an abstract base class, so we don't implement the actual logic here
// Subclasses must implement this method
throw new Error('InternalRunAction must be implemented by subclasses');
}
};
exports.QuickBooksBaseAction = QuickBooksBaseAction;
exports.QuickBooksBaseAction = QuickBooksBaseAction = __decorate([
(0, global_1.RegisterClass)(actions_1.BaseAction, 'QuickBooksBaseAction')
], QuickBooksBaseAction);
//# sourceMappingURL=quickbooks-base.action.js.map