quickbooks-node-promise
Version:
Connect to QuickBooks Online API with OAuth 2 with typescript on entities
1,212 lines (1,210 loc) • 109 kB
JavaScript
"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) => {