UNPKG

quickbooks-node-promise

Version:

Connect to QuickBooks Online API with OAuth 2 with typescript on entities

1,212 lines (1,210 loc) 109 kB
"use strict"; /** * @file Node.js client for QuickBooks V3 API * @name quickbooks-promise * @author Peter Brink <michael_cohen@intuit.com> * @license ISC * @copyright (c) 2019 Peter Brink * * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee * is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Modified from: * https://github.com/mcohen01/node-quickbooks * 2014 Michael Cohen */ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.Quickbooks = exports.ReportName = exports.EntityName = exports.DefaultStore = void 0; const uuid_1 = require("uuid"); const qs_1 = __importDefault(require("qs")); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); const node_fetch_1 = __importDefault(require("node-fetch")); const form_data_1 = __importDefault(require("form-data")); const csrf_1 = __importDefault(require("csrf")); const crypto_1 = __importDefault(require("crypto")); const helpers_1 = require("./helpers"); const csrf = new csrf_1.default(); class DefaultStore { constructor() { this.realmInfo = {}; this.realmInfo = {}; } getQBToken(getTokenData) { const realmID = getTokenData.realmID.toString(); if (!this.realmInfo[realmID]) { return Promise.reject("missing realm informaiton"); } const token = this.realmInfo[realmID]; if (!token) { return Promise.reject("Realm token information is missing"); } return Promise.resolve(token); } storeQBToken(storeTokenData) { const realmID = storeTokenData.realmID.toString(); this.realmInfo[realmID] = storeTokenData; return Promise.resolve(storeTokenData); } } exports.DefaultStore = DefaultStore; // missing Batch? var EntityName; (function (EntityName) { EntityName["Account"] = "Account"; EntityName["Attachable"] = "Attachable"; EntityName["Bill"] = "Bill"; EntityName["BillPayment"] = "BillPayment"; EntityName["Budget"] = "Budget"; EntityName["Class"] = "Class"; EntityName["CreditMemo"] = "CreditMemo"; EntityName["CompanyInfo"] = "CompanyInfo"; EntityName["Customer"] = "Customer"; EntityName["Department"] = "Department"; EntityName["Deposit"] = "Deposit"; EntityName["Employee"] = "Employee"; EntityName["Estimate"] = "Estimate"; EntityName["Exchangerate"] = "Exchangerate"; EntityName["Invoice"] = "Invoice"; EntityName["Item"] = "Item"; EntityName["JournalCode"] = "JournalCode"; EntityName["JournalEntry"] = "JournalEntry"; EntityName["Payment"] = "Payment"; EntityName["PaymentMethod"] = "PaymentMethod"; EntityName["Preferences"] = "Preferences"; EntityName["Purchase"] = "Purchase"; EntityName["PurchaseOrder"] = "PurchaseOrder"; EntityName["RefundReceipt"] = "RefundReceipt"; EntityName["SalesReceipt"] = "SalesReceipt"; EntityName["TaxAgency"] = "TaxAgency"; EntityName["TaxService"] = "TaxService"; EntityName["TaxCode"] = "TaxCode"; EntityName["TaxRate"] = "TaxRate"; EntityName["Term"] = "Term"; EntityName["TimeActivity"] = "TimeActivity"; EntityName["Transfer"] = "Transfer"; EntityName["Vendor"] = "Vendor"; EntityName["VendorCredit"] = "VendorCredit"; // Reports = "Reports" })(EntityName || (exports.EntityName = EntityName = {})); var ReportName; (function (ReportName) { ReportName["AccountList"] = "AccountList"; ReportName["AgedPayableDetail"] = "AgedPayableDetail"; ReportName["AgedPayables"] = "AgedPayables"; ReportName["AgedReceivableDetail"] = "AgedReceivableDetail"; ReportName["AgedReceivables"] = "AgedReceivables"; ReportName["BalanceSheet"] = "BalanceSheet"; ReportName["CashFlow"] = "CashFlow"; ReportName["ClassSales"] = "ClassSales"; ReportName["CustomerBalance"] = "CustomerBalance"; ReportName["CustomerBalanceDetail"] = "CustomerBalanceDetail"; ReportName["CustomerIncome"] = "CustomerIncome"; ReportName["CustomerSales"] = "CustomerSales"; ReportName["DepartmentSales"] = "DepartmentSales"; ReportName["GeneralLedger"] = "GeneralLedger"; ReportName["InventoryValuationSummary"] = "InventoryValuationSummary"; ReportName["ItemSales"] = "ItemSales"; ReportName["ProfitAndLoss"] = "ProfitAndLoss"; ReportName["ProfitAndLossDetail"] = "ProfitAndLossDetail"; ReportName["TaxSummary"] = "TaxSummary"; ReportName["TransactionList"] = "TransactionList"; ReportName["TrialBalance"] = "TrialBalance"; ReportName["VendorBalance"] = "VendorBalance"; ReportName["VendorBalanceDetail"] = "VendorBalanceDetail"; ReportName["VendorExpenses"] = "VendorExpenses"; })(ReportName || (exports.ReportName = ReportName = {})); class QBFetchError extends Error { constructor(msg, response) { super(msg); this.response = response; } } class QBResponseError extends Error { constructor(msg, errorResponse) { super(msg); this.errorResponse = errorResponse; } } class Quickbooks { /** * Node.js client encapsulating access to the QuickBooks V3 Rest API. An instance * of this class should be instantiated on behalf of each user and company accessing the api. */ constructor(appConfig, realmID, extra) { /** * Save token * @param tokenData - token information sent back from Quickbooks or as simple as { access_token: string }, Realm token information is depricated going forward */ this.saveToken = (tokenInput) => { let tokenData = null; if ("token" in tokenInput) { console.warn('tokenInput.token is depricated and will be removed in future versions on Quickbooks saveToken method'); tokenData = tokenInput.token; } else { tokenData = tokenInput; } let storeData = Object.assign(Object.assign({}, tokenData), { realmID: this.realmID, access_expire_timestamp: Date.now() + tokenData.expires_in * 1000, refresh_expire_timestamp: Date.now() + tokenData.x_refresh_token_expires_in * 1000 }); if (this.config.storeMethod === 'Internal') { this.storeTokenData = storeData; return Promise.resolve(storeData); } if (this.config.storeMethod === 'Function') { return this.config.saveToken(this.realmID, storeData, this.config, this.extra); } if (this.config.storeMethod === 'Class') { const appConfigStore = this.config; return appConfigStore.storeStrategy.storeQBToken(Object.assign({ realmID: this.realmID, token: tokenData }, storeData), this.config, this.extra); } }; /** * Creates new token for the realmID from the returned authorization code received in the callback request * @param authCode - The code returned in your callback as a param called "code" * @param realmID - DEPRICATED The company identifier in your callback as a param called "realmId" * @returns new token with expiration dates from storeStrategy */ this.createToken = (authCode, realmID) => __awaiter(this, void 0, void 0, function* () { if (realmID) { console.warn('realmID is depricated and will be removed in future versions on Quickbooks createToken method'); } if (!this.config.redirectUrl) throw new Error("RedirectUrl is missing"); if (!this.config.appKey) throw new Error("appKey is missing"); if (!this.config.appSecret) throw new Error("appScret is missing"); const auth = (0, helpers_1.getAuthBase64)(this.config); let fetchOptions = { method: "post", headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", Authorization: "Basic " + auth, }, body: qs_1.default.stringify({ grant_type: "authorization_code", code: authCode, redirect_uri: this.config.redirectUrl, //Make sure this path matches entry in application dashboard }), }; const response = yield (0, node_fetch_1.default)(_a.TOKEN_URL, fetchOptions); if (!response.ok) { throw new QBFetchError(response.statusText, response); } const newTokenData = yield response.json(); return this.saveToken(newTokenData); }); /** * Get token */ this.getToken = () => { const getStoreData = { realmID: this.realmID }; if (this.config.storeMethod === 'Internal') { return Promise.resolve(this.storeTokenData); } if (this.config.storeMethod === 'Function') { return this.config.getToken(this.realmID, this.config, this.extra); } if (this.config.storeMethod === 'Class') { return this.config.storeStrategy.getQBToken(getStoreData, this.config, this.extra); } }; /** * Get token and refresh if needed * * If config has autoRefresh false then return token regardless */ this.getTokenWithRefresh = () => __awaiter(this, void 0, void 0, function* () { let storeTokenData = yield this.getToken(); if (!this.config.autoRefresh) { return storeTokenData; } if (storeTokenData.refresh_token && !_a.isAccessTokenExpired(storeTokenData, this.config.autoRefreshBufferSeconds)) { storeTokenData = yield this.refreshWithAccessToken(storeTokenData.refresh_token); } return storeTokenData; }); this.refreshAcessTokenWithToken = (refreshToken) => __awaiter(this, void 0, void 0, function* () { if ("production" !== process.env.NODE_ENV && this.config.debug) { console.log("Refreshing quickbooks access_token"); } if (!refreshToken) throw Error("Refresh Token missing"); const auth = (0, helpers_1.getAuthBase64)(this.config); let fetchOptions = { method: "post", headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", Authorization: "Basic " + auth, }, body: qs_1.default.stringify({ grant_type: "refresh_token", refresh_token: refreshToken, }), }; const response = yield (0, node_fetch_1.default)(_a.TOKEN_URL, fetchOptions); if (!response.ok) { throw new QBFetchError(response.statusText, response); } const newTokenData = yield response.json(); return this.saveToken(newTokenData); }); /** * Use the refresh token to obtain a new access token. * @param token - has the refresh_token * @returns returns fresh token with access_token and refresh_token * * @deprecated use new method refreshAccessTokenWithToken going forward */ this.refreshWithAccessToken = (storeTokenOrRefreshString) => __awaiter(this, void 0, void 0, function* () { let refreshString = null; if (typeof storeTokenOrRefreshString === "string") { refreshString = storeTokenOrRefreshString; } else { refreshString = storeTokenOrRefreshString.refresh_token; } return this.refreshAcessTokenWithToken(refreshString); }); /** * Use the refresh token to obtain a new access token. */ this.refreshAccessToken = () => __awaiter(this, void 0, void 0, function* () { const tokenData = yield this.getToken(); if (!tokenData.refresh_token) throw Error("Refresh Token missing"); return this.refreshAcessTokenWithToken(tokenData.refresh_token); }); this.revokeAccessOtherToken = (token) => __awaiter(this, void 0, void 0, function* () { if (!this.config.appKey) throw new Error("appKey is missing"); if (!this.config.appSecret) throw new Error("appScret is missing"); if (!token) throw Error("Token missing to revoke"); const auth = (0, helpers_1.getAuthBase64)(this.config); let fetchOptions = { method: "post", headers: { Accept: "application/json", "Content-Type": "application/x-www-form-urlencoded", Authorization: "Basic " + auth, }, body: qs_1.default.stringify({ token: token, }), }; const response = yield (0, node_fetch_1.default)(_a.REVOKE_URL, fetchOptions); if (response.ok) { return response; } throw new QBFetchError(response.statusText, response); }); /** * Use either refresh token or access token to revoke access (OAuth2). * * @param useRefresh - boolean - Indicates which token to use: true to use the refresh token, false to use the access token. */ this.revokeAccess = (useRefresh) => __awaiter(this, void 0, void 0, function* () { const token = yield this.getToken(); const revokeToken = useRefresh ? token.refresh_token : token.access_token; return this.revokeAccessOtherToken(revokeToken); }); /** * Validate id_token * */ this.validateIdToken = () => __awaiter(this, void 0, void 0, function* () { const token = yield this.getToken(); if (!token.id_token) throw Error("ID Token missing"); if (!this.config.appKey) throw new Error("appKey is missing"); // Decode ID Token const token_parts = token.id_token.split("."); const id_token_header = JSON.parse(atob(token_parts[0])); const id_token_payload = JSON.parse(atob(token_parts[1])); const id_token_signature = atob(token_parts[2]); // // Step 1 : First check if the issuer is as mentioned in "issuer" if (id_token_payload.iss != _a.IDTOKEN_ISSUER_URL) return false; // Step 2 : check if the aud field in idToken is same as application's key if (id_token_payload.aud != this.config.appKey) return false; // Step 3 : ensure the timestamp has not elapsed if (id_token_payload.exp < Date.now() / 1000) return false; let fetchOptions = { method: "get", headers: { Accept: "application/json", }, }; return (0, node_fetch_1.default)(_a.JWKS_URL, fetchOptions) .then((response) => { if (response.ok) { return response.json(); } else { throw new QBFetchError(response.statusText, response); } }) .then((json) => { const key = json.keys.find((el) => el.kid == id_token_header.kid); const cert = this.getPublicKey(key.n, key.e); if (!token.id_token) { throw new Error("ID Token missing"); } return jsonwebtoken_1.default.verify(token.id_token, cert); }) .then((res) => { if (res) { return true; } }); }); /** * get Public Key * @param modulus * @param exponent */ this.getPublicKey = (modulus, exponent) => { const getPem = require("rsa-pem-from-mod-exp"); const pem = getPem(modulus, exponent); return pem; }; this.verifyWebhook = (payload, signature) => { return _a.verifyWebhook(this.config.webhookVerifierToken, payload, signature); }; /*** API HELPER FUNCTIONS ***/ this.request = (verb, options, entity) => __awaiter(this, void 0, void 0, function* () { var _b; let token = yield this.getTokenWithRefresh(); if (!token) throw Error("Token missing"); if (!token.access_token) throw Error("Access Token missing"); const opts = { qs: options.qs || {}, headers: options.headers || {}, returnHeadersInBody: options.returnHeadersInBody || false, }; let url = null; if (options.fullurl) { url = options.url; } else { url = _a.getApiEndpoint(this.config.useProduction) + this.realmID + options.url; } if (entity && entity.allowDuplicateDocNum) { delete entity.allowDuplicateDocNum; opts.qs.include = "allowduplicatedocnum"; } if (verb == "post") { opts.qs.requestid = (0, uuid_1.v4)(); } if (this.config.minorversion) { opts.qs.minorversion = this.config.minorversion; } opts.headers["Authorization"] = "Bearer " + token.access_token; opts.headers["accept"] = "application/json"; if (entity !== null) { opts.body = JSON.stringify(entity); opts.headers["Content-Type"] = "application/json"; } if (options.formData) { opts.body = options.formData; } const fetchOptions = { method: verb, headers: opts.headers, body: opts.body, }; url = `${url}?${qs_1.default.stringify(opts.qs)}`; if ("production" !== process.env.NODE_ENV && this.config.debug) { console.log("invoking endpoint:", url); console.log("fetch options", fetchOptions); } const response = yield (0, node_fetch_1.default)(url, fetchOptions); if (response.ok) { const returnedObject = yield response.json(); if (opts.returnHeadersInBody) { const specialHeaders = { intuitTid: response.headers.get("intuit_tid"), server: response.headers.get("Server"), qboVersion: response.headers.get("QBO-Version"), expires: response.headers.get("Expires"), date: response.headers.get("Date"), }; return Object.assign(Object.assign({}, returnedObject), { specialHeaders }); } return returnedObject; } else { try { const body = yield response.json(); if ((_b = body === null || body === void 0 ? void 0 : body.Fault) === null || _b === void 0 ? void 0 : _b.Error) { throw new QBResponseError(`Error of type ${body.Fault.type}`, body); } } catch (e) { // ignore throw e; } throw new QBFetchError(response.statusText, response); } }); this.requestPdf = (entityName, id) => __awaiter(this, void 0, void 0, function* () { let token = yield this.getTokenWithRefresh(); if (!token) throw Error("Token missing"); if (!token.access_token) throw Error("Access Token missing"); const fetchOptions = { method: "get", headers: { Authorization: `Bearer ${token.access_token}`, accept: "application/pdf", }, }; const qsv = {}; if (this.config.minorversion) { qsv.minorversion = this.config.minorversion; } const sendUrl = `${_a.getApiEndpoint(this.config.useProduction)}${this.realmID}/${entityName.toLowerCase()}/${id}/pdf?${qs_1.default.stringify(qsv)}`; if ("production" !== process.env.NODE_ENV && this.config.debug) { console.log("invoking endpoint:", sendUrl); console.log("fetch options", fetchOptions); } const response = yield (0, node_fetch_1.default)(sendUrl, fetchOptions); if (response.ok) { return response.buffer(); } else { throw new QBFetchError(response.statusText, response); } }); // ********************** CRUD Api ********************** this.create = (entityName, entity) => { const url = "/" + entityName.toLowerCase(); return this.request("post", { url: url, returnHeadersInBody: true }, entity); }; this.read = (entityName, id, options) => { let url = "/" + entityName.toLowerCase(); if (id) url = `${url}/${id}`; return this.request("get", { url: url, qs: options, returnHeadersInBody: true }, null); }; this.update = (entityName, entity) => { if (entityName === EntityName.Exchangerate) { throw new Error("Exchangerate entity cannot be updated"); } let url = "/" + entityName.toLowerCase(); let qs = { operation: "update" }; let opts = { url: url, qs: qs, returnHeadersInBody: true }; return this.request("post", opts, entity); }; this.delete = (entityName, idOrEntity) => __awaiter(this, void 0, void 0, function* () { // requires minimum Id and SyncToken // if passed Id as numeric value then grab entity and send it to delete let url = "/" + entityName.toLowerCase(); let qs = { operation: "delete" }; if (typeof idOrEntity === 'object') { return this.request("post", { url: url, qs: qs, returnHeadersInBody: true }, idOrEntity); } else { const entity = yield this.read(entityName, idOrEntity); return this.request("post", { url: url, qs: qs, returnHeadersInBody: true }, entity); } }); this.void = (entityName, idOrEntity) => __awaiter(this, void 0, void 0, function* () { // requires minimum Id and SyncToken // if passed Id as numeric value then grab entity and send it to delete const url = "/" + entityName.toLowerCase(); let qs = { operation: "void" }; if (typeof idOrEntity === 'object') { return this.request("post", { url: url, qs: qs, returnHeadersInBody: true }, idOrEntity); } else { const entity = yield this.read(entityName, idOrEntity); return this.request("post", { url: url, qs: qs, returnHeadersInBody: true }, entity); } }); // ********************** Query Api ********************** this.query = (entityName, queryInput) => __awaiter(this, void 0, void 0, function* () { const [query, queryData] = (0, helpers_1.getQueryString)(entityName, queryInput !== null && queryInput !== void 0 ? queryInput : null); if ("production" !== process.env.NODE_ENV && this.config.debug) { console.log("using query:", query); console.log("query data:", queryData); } const url = "/query"; let qs = { query: query, }; if (queryData === null || queryData === void 0 ? void 0 : queryData.count) { throw new Error("Count is not supported, use count[Entity] for count"); } const data = yield this.request("get", { url: url, qs: qs, returnHeadersInBody: true }, null); if ((queryData === null || queryData === void 0 ? void 0 : queryData.fetchAll) && (queryData === null || queryData === void 0 ? void 0 : queryData.limit) && data && data.QueryResponse && data.QueryResponse.maxResults === queryData.limit && data.QueryResponse[entityName] && Array.isArray(data.QueryResponse[entityName])) { if (!queryData.offset) { queryData.offset = queryData.limit; } else { queryData.offset = queryData.offset + queryData.limit; } const more = yield this.query(entityName, queryData); if (data.QueryResponse[entityName]) { data.QueryResponse[entityName] = data.QueryResponse[entityName].concat(more.QueryResponse[entityName] || []); data.QueryResponse.maxResults = data.QueryResponse.maxResults + (more.QueryResponse.maxResults || 0); data.QueryResponse.totalCount = data.QueryResponse.totalCount + (more.QueryResponse.totalCount || 0); data.time = more.time || data.time; } } return data; }); this.queryCount = (entityName, queryInput) => __awaiter(this, void 0, void 0, function* () { const [query, queryData] = (0, helpers_1.getQueryString)(entityName, queryInput !== null && queryInput !== void 0 ? queryInput : null, true); const url = "/query"; let qs = { query: query, }; return this.request("get", { url: url, qs: qs, returnHeadersInBody: true }, null); }); // ********************** Report Api ********************** this.report = (reportType, criteria) => { let url = "/reports/" + reportType; return this.request("get", { url: url, qs: criteria }, null); }; this.pluralize = (s) => { const last = s.substring(s.length - 1); if (last === "s") { return s + "es"; } else if (last === "y") { return s.substring(0, s.length - 1) + "ies"; } else { return s + "s"; } }; this.unwrap = (data, baseProperty) => { const name = baseProperty; return (data || {})[name] || data; }; /*** API CALLS HERE ***/ /** * Get user info (OAuth2). * * fields returned based on scope * givenName, familyName - profile scope * Email, EmailVerified - email scope * Phone, PhoneVerified - phone scope * Address - address scope */ this.getUserInfo = () => { return this.request("get", { url: _a.getUserInfoEndpoint(this.config.useProduction), fullurl: true }, null); }; /** * Batch operation to enable an application to perform multiple operations in a single request. * The following batch items are supported: create update delete query * The maximum number of batch items in a single request is 25. * * @param items - JavaScript array of batch items */ this.batch = (items) => { return this.request("post", { url: "/batch" }, { BatchItemRequest: items }); }; /** * The change data capture (CDC) operation returns a list of entities that have changed since a specified time. * * @param entities - Comma separated list or JavaScript array of entities to search for changes * @param since - JS Date object, JS Date milliseconds, or string in ISO 8601 - to look back for changes until */ this.changeDataCapture = (entities, since) => { const dateString = (0, helpers_1.getDateString)(since); let url = "/cdc"; let qs = { entities: typeof entities === "string" ? entities : entities.join(","), changedSince: dateString, }; return this.request("get", { url: url, qs: qs, returnHeadersInBody: true }, null); }; /** * Updates QuickBooks version of Attachable * * @param attachable - The persistent Attachable, including Id and SyncToken fields */ this.updateAttachable = (attachable) => { return this.update(EntityName.Attachable, attachable); }; /** * Uploads a file as an Attachable in QBO, optionally linking it to the specified * QBO Entity. * * @param filename - the name of the file * @param contentType - the mime type of the file * @param buffer - Buffer of file contents * @param entityType - optional string name of the QBO entity the Attachable will be linked to (e.g. Invoice) * @param entityId - optional Id of the QBO entity the Attachable will be linked to */ this.upload = (filename, contentType, buffer, entityType, entityId) => __awaiter(this, void 0, void 0, function* () { var _c, _d; const formData = new form_data_1.default(); formData.append("file_metadata_01", JSON.stringify({ AttachableRef: [ { EntityRef: { type: entityType, value: entityId + "", }, }, ], ContentType: contentType, FileName: filename }), { filename: "attachment.json", contentType: "application/json" }); formData.append("file_content_01", buffer, { filename, contentType }); const response = yield this.request("post", { url: "/upload", formData }, null); if ((_d = (_c = response === null || response === void 0 ? void 0 : response.AttachableResponse) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.Fault) { const fault = response.AttachableResponse[0]; throw new QBResponseError(`Error of type ${fault.Fault.type}`, fault); } return response; }); /** * Downloads the file associated with the specified Attachable. */ this.download = (id) => __awaiter(this, void 0, void 0, function* () { var _e, _f; const response = yield this.request("get", { url: `/download/${id}` }, null); if ((_f = (_e = response === null || response === void 0 ? void 0 : response.AttachableResponse) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.Fault) { const fault = response.AttachableResponse[0]; throw new QBResponseError(`Error of type ${fault.Fault.type}`, fault); } return response; }); /** * Creates the Account in QuickBooks * * @param {object} account - The unsaved account, to be persisted in QuickBooks */ this.createAccount = (account) => { return this.create(EntityName.Account, account); }; /** * Creates the Attachable in QuickBooks * * @param {object} attachable - The unsaved attachable, to be persisted in QuickBooks */ this.createAttachable = (attachable) => { return this.create(EntityName.Attachable, attachable); }; /** * Creates the Bill in QuickBooks * * @param {object} bill - The unsaved bill, to be persisted in QuickBooks */ this.createBill = (bill) => { return this.create(EntityName.Bill, bill); }; /** * Creates the BillPayment in QuickBooks * * @param {object} billPayment - The unsaved billPayment, to be persisted in QuickBooks */ this.createBillPayment = (billPayment) => { return this.create(EntityName.BillPayment, billPayment); }; /** * Creates the Class in QuickBooks * * @param classqb - The unsaved class, to be persisted in QuickBooks */ this.createClass = (classqb) => { return this.create(EntityName.Class, classqb); }; /** * Creates the CreditMemo in QuickBooks * * @param {object} creditMemo - The unsaved creditMemo, to be persisted in QuickBooks */ this.createCreditMemo = (creditMemo) => { return this.create(EntityName.CreditMemo, creditMemo); }; /** * Creates the Customer in QuickBooks * * @param {object} customer - The unsaved customer, to be persisted in QuickBooks */ this.createCustomer = (customer) => { return this.create(EntityName.Customer, customer); }; /** * Creates the Department in QuickBooks * * @param {object} department - The unsaved department, to be persisted in QuickBooks */ this.createDepartment = (department) => { return this.create(EntityName.Department, department); }; /** * Creates the Deposit in QuickBooks * * @param {object} deposit - The unsaved Deposit, to be persisted in QuickBooks */ this.createDeposit = (deposit) => { return this.create(EntityName.Deposit, deposit); }; /** * Creates the Employee in QuickBooks * * @param {object} employee - The unsaved employee, to be persisted in QuickBooks */ this.createEmployee = (employee) => { return this.create(EntityName.Employee, employee); }; /** * Creates the Estimate in QuickBooks * * @param {object} estimate - The unsaved estimate, to be persisted in QuickBooks */ this.createEstimate = (estimate) => { return this.create(EntityName.Estimate, estimate); }; /** * Creates the Invoice in QuickBooks * * @param {object} invoice - The unsaved invoice, to be persisted in QuickBooks */ this.createInvoice = (invoice) => { return this.create(EntityName.Invoice, invoice); }; /** * Creates the Item in QuickBooks * * @param {object} item - The unsaved item, to be persisted in QuickBooks */ this.createItem = (item) => { return this.create(EntityName.Item, item); }; /** * Creates the JournalCode in QuickBooks * * @param {object} journalCode - The unsaved journalCode, to be persisted in QuickBooks */ this.createJournalCode = (journalCode) => { return this.create(EntityName.JournalCode, journalCode); }; /** * Creates the JournalEntry in QuickBooks * * @param {object} journalEntry - The unsaved journalEntry, to be persisted in QuickBooks */ this.createJournalEntry = (journalEntry) => { return this.create(EntityName.JournalEntry, journalEntry); }; /** * Creates the Payment in QuickBooks * * @param {object} payment - The unsaved payment, to be persisted in QuickBooks */ this.createPayment = (payment) => { return this.create(EntityName.Payment, payment); }; /** * Creates the PaymentMethod in QuickBooks * * @param {object} paymentMethod - The unsaved paymentMethod, to be persisted in QuickBooks */ this.createPaymentMethod = (paymentMethod) => { return this.create(EntityName.PaymentMethod, paymentMethod); }; /** * Creates the Purchase in QuickBooks * * @param {object} purchase - The unsaved purchase, to be persisted in QuickBooks */ this.createPurchase = (purchase) => { return this.create(EntityName.Purchase, purchase); }; /** * Creates the PurchaseOrder in QuickBooks * * @param {object} purchaseOrder - The unsaved purchaseOrder, to be persisted in QuickBooks */ this.createPurchaseOrder = (purchaseOrder) => { return this.create(EntityName.PurchaseOrder, purchaseOrder); }; /** * Creates the RefundReceipt in QuickBooks * * @param {object} refundReceipt - The unsaved refundReceipt, to be persisted in QuickBooks */ this.createRefundReceipt = (refundReceipt) => { return this.create(EntityName.RefundReceipt, refundReceipt); }; /** * Creates the SalesReceipt in QuickBooks * * @param {object} salesReceipt - The unsaved salesReceipt, to be persisted in QuickBooks */ this.createSalesReceipt = (salesReceipt) => { return this.create(EntityName.SalesReceipt, salesReceipt); }; /** * Creates the TaxAgency in QuickBooks * * @param {object} taxAgency - The unsaved taxAgency, to be persisted in QuickBooks */ this.createTaxAgency = (taxAgency) => { return this.create(EntityName.TaxAgency, taxAgency); }; /** * Creates the Term in QuickBooks * * @param {object} term - The unsaved term, to be persisted in QuickBooks */ this.createTerm = (term) => { return this.create(EntityName.Term, term); }; /** * Creates the TimeActivity in QuickBooks * * @param {object} timeActivity - The unsaved timeActivity, to be persisted in QuickBooks */ this.createTimeActivity = (timeActivity) => { return this.create(EntityName.TimeActivity, timeActivity); }; /** * Creates the Transfer in QuickBooks * * @param {object} transfer - The unsaved Transfer, to be persisted in QuickBooks */ this.createTransfer = (transfer) => { return this.create(EntityName.Transfer, transfer); }; /** * Creates the Vendor in QuickBooks * * @param {object} vendor - The unsaved vendor, to be persisted in QuickBooks */ this.createVendor = (vendor) => { return this.create(EntityName.Vendor, vendor); }; /** * Creates the VendorCredit in QuickBooks * * @param {object} vendorCredit - The unsaved vendorCredit, to be persisted in QuickBooks */ this.createVendorCredit = (vendorCredit) => { return this.create(EntityName.VendorCredit, vendorCredit); }; /** * Creates the TaxService in QuickBooks * * Different return than other create methods, does not include entity name in top level * * @param {object} taxService - The unsaved taxService, to be persisted in QuickBooks */ this.createTaxService = (taxService) => { return this.request("post", { url: "/taxservice/taxcode" }, taxService); }; /** * Retrieves the Account from QuickBooks * * @param Id - The Id of persistent Account */ this.getAccount = (id) => { return this.read(EntityName.Account, id); }; /** * Retrieves the Attachable from QuickBooks * * @param Id - The Id of persistent Attachable */ this.getAttachable = (id) => { return this.read(EntityName.Attachable, id); }; /** * Retrieves the Bill from QuickBooks * * @param Id - The Id of persistent Bill */ this.getBill = (id) => { return this.read(EntityName.Bill, id); }; /** * Retrieves the BillPayment from QuickBooks * * @param Id - The Id of persistent BillPayment */ this.getBillPayment = (id) => { return this.read(EntityName.BillPayment, id); }; /** * Retrieves the Class from QuickBooks * * @param Id - The Id of persistent Class */ this.getClass = (id) => { return this.read(EntityName.Class, id); }; /** * Retrieves the CompanyInfo from QuickBooks * * @param Id - The Id of persistent CompanyInfo */ this.getCompanyInfo = (id) => { return this.read(EntityName.CompanyInfo, id); }; /** * Retrieves the CreditMemo from QuickBooks * * @param Id - The Id of persistent CreditMemo */ this.getCreditMemo = (id) => { return this.read(EntityName.CreditMemo, id); }; /** * Retrieves the Customer from QuickBooks * * @param Id - The Id of persistent Customer */ this.getCustomer = (id) => { return this.read(EntityName.Customer, id); }; /** * Retrieves the Department from QuickBooks * * @param Id - The Id of persistent Department */ this.getDepartment = (id) => { return this.read(EntityName.Department, id); }; /** * Retrieves the Deposit from QuickBooks * * @param Id - The Id of persistent Deposit */ this.getDeposit = (id) => { return this.read(EntityName.Deposit, id); }; /** * Retrieves the Employee from QuickBooks * * @param Id - The Id of persistent Employee */ this.getEmployee = (id) => { return this.read(EntityName.Employee, id); }; /** * Retrieves the Estimate from QuickBooks * * @param Id - The Id of persistent Estimate */ this.getEstimate = (id) => { return this.read(EntityName.Estimate, id); }; /** * Retrieves an ExchangeRate from QuickBooks * * @param options - An object with options including the required `sourcecurrencycode` parameter and optional `asofdate` parameter. */ this.getExchangeRate = (options) => { const url = "/exchangerate"; return this.read(EntityName.Exchangerate, null, options); }; /** * Retrieves the Invoice from QuickBooks * * @param Id - The Id of persistent Invoice */ this.getInvoice = (id) => { return this.read(EntityName.Invoice, id); }; /** * Retrieves the Item from QuickBooks * * @param Id - The Id of persistent Item */ this.getItem = (id) => { return this.read(EntityName.Item, id); }; /** * Retrieves the JournalCode from QuickBooks * * @param Id - The Id of persistent JournalCode */ this.getJournalCode = (id) => { return this.read(EntityName.JournalCode, id); }; /** * Retrieves the JournalEntry from QuickBooks * * @param Id - The Id of persistent JournalEntry */ this.getJournalEntry = (id) => { return this.read(EntityName.JournalEntry, id); }; /** * Retrieves the Payment from QuickBooks * * @param Id - The Id of persistent Payment */ this.getPayment = (id) => { return this.read(EntityName.Payment, id); }; /** * Retrieves the PaymentMethod from QuickBooks * * @param Id - The Id of persistent PaymentMethod */ this.getPaymentMethod = (id) => { return this.read(EntityName.PaymentMethod, id); }; /** * Retrieves the Preferences from QuickBooks * */ this.getPreferences = () => { return this.read(EntityName.Preferences, null); }; /** * Retrieves the Purchase from QuickBooks * * @param Id - The Id of persistent Purchase */ this.getPurchase = (id) => { return this.read(EntityName.Purchase, id); }; /** * Retrieves the PurchaseOrder from QuickBooks * * @param Id - The Id of persistent PurchaseOrder */ this.getPurchaseOrder = (id) => { return this.read(EntityName.PurchaseOrder, id); }; /** * Retrieves the RefundReceipt from QuickBooks * * @param Id - The Id of persistent RefundReceipt */ this.getRefundReceipt = (id) => { return this.read(EntityName.RefundReceipt, id); }; /** * Retrieves the Reports from QuickBooks * * @param Id - The Id of persistent Reports */ // getReports = (id: string | number) => { // return this.read(EntityName.Reports, id); // }; /** * Retrieves the SalesReceipt from QuickBooks * * @param Id - The Id of persistent SalesReceipt */ this.getSalesReceipt = (id) => { return this.read(EntityName.SalesReceipt, id); }; /** * Retrieves the TaxAgency from QuickBooks * * @param Id - The Id of persistent TaxAgency */ this.getTaxAgency = (id) => { return this.read(EntityName.TaxAgency, id); }; /** * Retrieves the TaxCode from QuickBooks * * @param Id - The Id of persistent TaxCode */ this.getTaxCode = (id) => { return this.read(EntityName.TaxCode, id); }; /** * Retrieves the TaxRate from QuickBooks * * @param Id - The Id of persistent TaxRate */ this.getTaxRate = (id) => { return this.read(EntityName.TaxRate, id); }; /** * Retrieves the Term from QuickBooks * * @param Id - The Id of persistent Term */ this.getTerm = (id) => { return this.read(EntityName.Term, id); }; /** * Retrieves the TimeActivity from QuickBooks * * @param Id - The Id of persistent TimeActivity */ this.getTimeActivity = (id) => { return this.read(EntityName.TimeActivity, id); }; /** * Retrieves the Transfer from QuickBooks * * @param Id - The Id of persistent Term */ this.getTransfer = (id) => { return this.read(EntityName.Transfer, id); }; /** * Retrieves the Vendor from QuickBooks * * @param Id - The Id of persistent Vendor */ this.getVendor = (id) => { return this.read(EntityName.Vendor, id); }; /** * Retrieves the VendorCredit from QuickBooks * * @param Id - The Id of persistent VendorCredit */ this.getVendorCredit = (id) => {