Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quickbooks Usability Audit #14712

Merged
merged 22 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default {
key: "quickbooks-create-ap-aging-report",
name: "Create AP Aging Detail Report",
description: "Creates an AP aging report in Quickbooks Online. [See the documentation](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/apagingdetail#query-a-report)",
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
quickbooks,
Expand Down
119 changes: 82 additions & 37 deletions components/quickbooks/actions/create-bill/create-bill.mjs
Original file line number Diff line number Diff line change
@@ -1,84 +1,129 @@
import { ConfigurationError } from "@pipedream/platform";
import quickbooks from "../../quickbooks.app.mjs";
import { parseLineItems } from "../../common/utils.mjs";

export default {
key: "quickbooks-create-bill",
name: "Create Bill",
description: "Creates a bill. [See docs here](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/bill#create-a-bill)",
version: "0.1.6",
description: "Creates a bill. [See the documentation](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/bill#create-a-bill)",
version: "0.1.7",
type: "action",
props: {
quickbooks,
vendorRefValue: {
label: "Vendor Ref Value",
type: "string",
description: "Reference to the vendor for this transaction. Query the Vendor name list resource to determine the appropriate Vendor object for this reference. Use `Vendor.Id` from that object for `VendorRef.value`.",
},
lineItems: {
description: "Individual line items of a transaction. Valid Line types include: `ItemBasedExpenseLine` and `AccountBasedExpenseLine`. One minimum line item required for the request to succeed. E.g `[ { \"DetailType\": \"AccountBasedExpenseLineDetail\", \"Amount\": 200.0, \"AccountBasedExpenseLineDetail\": { \"AccountRef\": { \"value\": \"1\" } } } ]`",
propDefinition: [
quickbooks,
"lineItems",
"vendorIds",
],
},
vendorRefName: {
label: "Vendor Reference Name",
type: "string",
description: "Reference to the vendor for this transaction. Query the Vendor name list resource to determine the appropriate Vendor object for this reference. Use `Vendor.Name` from that object for `VendorRef.name`.",
optional: true,
label: "Vendor ID",
description: "Reference to the vendor for this transaction",
optional: false,
},
currencyRefValue: {
propDefinition: [
quickbooks,
"currencyRefValue",
"currency",
],
},
currencyRefName: {
lineItemsAsObjects: {
propDefinition: [
quickbooks,
"currencyRefName",
"lineItemsAsObjects",
],
reloadProps: true,
},
minorVersion: {
propDefinition: [
quickbooks,
"minorVersion",
],
},
async additionalProps() {
const props = {};
if (this.lineItemsAsObjects) {
props.lineItems = {
type: "string[]",
label: "Line Items",
description: "Line items of a bill. Set DetailType to `AccountBasedExpenseLineDetail`. Example: `{ \"DetailType\": \"AccountBasedExpenseLineDetail\", \"Amount\": 100.0, \"AccountBasedExpenseLineDetail\": { \"AccountRef\": { \"name\": \"Advertising\", \"value\": \"1\" } } }`",
};
return props;
}
props.numLineItems = {
type: "integer",
label: "Number of Line Items",
description: "The number of line items to enter",
reloadProps: true,
};
if (!this.numLineItems) {
return props;
}
for (let i = 1; i <= this.numLineItems; i++) {
props[`account_${i}`] = {
type: "string",
label: `Line ${i} - Account ID`,
options: async ({ page }) => {
return this.quickbooks.getPropOptions({
page,
resource: "Account",
mapper: ({
Id: value, Name: label,
}) => ({
value,
label,
}),
});
},
};
props[`amount_${i}`] = {
type: "string",
label: `Line ${i} - Amount`,
};
}
return props;
},
methods: {
buildLineItems() {
const lineItems = [];
for (let i = 1; i <= this.numLineItems; i++) {
lineItems.push({
DetailType: "AccountBasedExpenseLineDetail",
Amount: this[`amount_${i}`],
AccountBasedExpenseLineDetail: {
AccountRef: {
value: this[`account_${i}`],
},
},
});
}
return lineItems;
},
},
async run({ $ }) {
if (!this.vendorRefValue || !this.lineItems) {
if (!this.vendorRefValue || (!this.numLineItems && !this.lineItemsAsObjects)) {
throw new ConfigurationError("Must provide vendorRefValue, and lineItems parameters.");
}

try {
this.lineItems = this.lineItems.map((lineItem) => typeof lineItem === "string"
? JSON.parse(lineItem)
: lineItem);
} catch (error) {
throw new ConfigurationError(`We got an error trying to parse the LineItems. Error: ${error}`);
}
const lines = this.lineItemsAsObjects
? parseLineItems(this.lineItems)
: this.buildLineItems();

lines.forEach((line) => {
if (line.DetailType !== "AccountBasedExpenseLineDetail") {
throw new ConfigurationError("Line Item DetailType must be `AccountBasedExpenseLineDetail`");
}
});

const response = await this.quickbooks.createBill({
$,
data: {
VendorRef: {
value: this.vendorRefValue,
name: this.vendorRefName,
},
Line: this.lineItems,
Line: lines,
CurrencyRef: {
value: this.currencyRefValue,
name: this.currencyRefName,
},
},
params: {
minorversion: this.minorVersion,
},
});

if (response) {
$.export("summary", `Successfully created bill with id ${response.Bill.Id}`);
$.export("summary", `Successfully created bill with ID ${response.Bill.Id}`);
}

return response;
Expand Down
15 changes: 3 additions & 12 deletions components/quickbooks/actions/create-customer/create-customer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import quickbooks from "../../quickbooks.app.mjs";
export default {
key: "quickbooks-create-customer",
name: "Create Customer",
description: "Creates a customer. [See docs here](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/customer#create-a-customer)",
version: "0.1.6",
description: "Creates a customer. [See the documentation](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/customer#create-a-customer)",
version: "0.1.7",
type: "action",
props: {
quickbooks,
Expand Down Expand Up @@ -45,12 +45,6 @@ export default {
"suffix",
],
},
minorVersion: {
propDefinition: [
quickbooks,
"minorVersion",
],
},
},
async run({ $ }) {
if (
Expand All @@ -70,13 +64,10 @@ export default {
FamilyName: this.familyName,
GivenName: this.givenName,
},
params: {
minorversion: this.minorVersion,
},
});

if (response) {
$.export("summary", `Successfully created customer with id ${response.Customer.Id}`);
$.export("summary", `Successfully created customer with ID ${response.Customer.Id}`);
}

return response;
Expand Down
116 changes: 79 additions & 37 deletions components/quickbooks/actions/create-invoice/create-invoice.mjs
Original file line number Diff line number Diff line change
@@ -1,83 +1,125 @@
import { ConfigurationError } from "@pipedream/platform";
import quickbooks from "../../quickbooks.app.mjs";
import { parseLineItems } from "../../common/utils.mjs";

export default {
key: "quickbooks-create-invoice",
name: "Create Invoice",
description: "Creates an invoice. [See docs here](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/invoice#create-an-invoice)",
version: "0.1.6",
description: "Creates an invoice. [See the documentation](https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/invoice#create-an-invoice)",
version: "0.1.7",
type: "action",
props: {
quickbooks,
lineItems: {
propDefinition: [
quickbooks,
"lineItems",
],
},
customerRefValue: {
label: "Customer Reference Value",
type: "string",
description: "Reference to a customer or job. Query the Customer name list resource to determine the appropriate Customer object for this reference. Use `Customer.Id` from that object for `CustomerRef.value`.",
},
customerRefName: {
propDefinition: [
quickbooks,
"customerRefName",
"customer",
],
},
currencyRefValue: {
propDefinition: [
quickbooks,
"currencyRefValue",
"currency",
],
},
currencyRefName: {
lineItemsAsObjects: {
propDefinition: [
quickbooks,
"currencyRefName",
"lineItemsAsObjects",
],
reloadProps: true,
},
minorVersion: {
propDefinition: [
quickbooks,
"minorVersion",
],
},
async additionalProps() {
const props = {};
if (this.lineItemsAsObjects) {
props.lineItems = {
type: "string[]",
label: "Line Items",
description: "Line items of an invoice. Set DetailType to `SalesItemLineDetail`, `GroupLineDetail`, or `DescriptionOnly`. Example: `{ \"DetailType\": \"SalesItemLineDetail\", \"Amount\": 100.0, \"SalesItemLineDetail\": { \"ItemRef\": { \"name\": \"Services\", \"value\": \"1\" } } }`",
};
return props;
}
props.numLineItems = {
type: "integer",
label: "Number of Line Items",
description: "The number of line items to enter",
reloadProps: true,
};
if (!this.numLineItems) {
return props;
}
for (let i = 1; i <= this.numLineItems; i++) {
props[`item_${i}`] = {
type: "string",
label: `Line ${i} - Item ID`,
options: async ({ page }) => {
return this.quickbooks.getPropOptions({
page,
resource: "Item",
mapper: ({
Id: value, Name: label,
}) => ({
value,
label,
}),
});
},
};
props[`amount_${i}`] = {
type: "string",
label: `Line ${i} - Amount`,
};
}
return props;
},
methods: {
buildLineItems() {
const lineItems = [];
for (let i = 1; i <= this.numLineItems; i++) {
lineItems.push({
DetailType: "SalesItemLineDetail",
Amount: this[`amount_${i}`],
SalesItemLineDetail: {
ItemRef: {
value: this[`item_${i}`],
},
},
});
}
return lineItems;
},
},
async run({ $ }) {
if (!this.lineItems || !this.customerRefValue) {
if ((!this.numLineItems && !this.lineItemsAsObjects) || !this.customerRefValue) {
throw new ConfigurationError("Must provide lineItems, and customerRefValue parameters.");
}

try {
this.lineItems = this.lineItems.map((lineItem) => typeof lineItem === "string"
? JSON.parse(lineItem)
: lineItem);
} catch (error) {
throw new ConfigurationError(`We got an error trying to parse the LineItems. Error: ${error}`);
}
const lines = this.lineItemsAsObjects
? parseLineItems(this.lineItems)
: this.buildLineItems();

lines.forEach((line) => {
if (line.DetailType !== "SalesItemLineDetail" && line.DetailType !== "GroupLineDetail" && line.DetailType !== "DescriptionOnly") {
throw new ConfigurationError("Line Item DetailType must be `SalesItemLineDetail`, `GroupLineDetail`, or `DescriptionOnly`");
}
});

const response = await this.quickbooks.createInvoice({
$,
data: {
Line: this.lineItems,
Line: lines,
CustomerRef: {
value: this.customerRefValue,
name: this.customerRefName,
},
CurrencyRef: {
value: this.currencyRefValue,
name: this.currencyRefName,
},
},
params: {
minorversion: this.minorVersion,
},
});

if (response) {
$.export("summary", `Successfully created invoice with id ${response.Invoice.Id}`);
$.export("summary", `Successfully created invoice with ID ${response.Invoice.Id}`);
}

return response;
Expand Down
Loading
Loading