UNPKG

@memberjunction/actions-bizapps-accounting

Version:

Accounting system integration actions for MemberJunction

172 lines 7.25 kB
"use strict"; 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