Skip to content
Open
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
1,010 changes: 986 additions & 24 deletions apps/docs/content/docs/en/integrations/quickbooks.mdx

Large diffs are not rendered by default.

543 changes: 506 additions & 37 deletions apps/sim/blocks/blocks/quickbooks.ts

Large diffs are not rendered by default.

66 changes: 63 additions & 3 deletions apps/sim/lib/integrations/integrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -14519,8 +14519,8 @@
"type": "quickbooks",
"slug": "quickbooks",
"name": "QuickBooks",
"description": "Read and manage QuickBooks Online company and master data",
"longDescription": "Connect one QuickBooks Online company to read company, master-data, purchase-order, and bill records and to create or update customers, vendors, and basic products or services.",
"description": "Manage QuickBooks Online company, master data, sales, and receivables",
"longDescription": "Connect one QuickBooks Online company to manage master data and bounded sales and receivables workflows, while preserving existing purchase-order and bill reads.",
"bgColor": "#2CA01C",
"iconName": "QuickBooksIcon",
"docsUrl": "https://docs.sim.ai/integrations/quickbooks",
Expand Down Expand Up @@ -14557,6 +14557,66 @@
"name": "Items: Update",
"description": "Sparse-update a Service or Non-inventory item in QuickBooks Online"
},
{
"name": "Sales: Read Transactions",
"description": "List or read one estimate, invoice, sales receipt, payment, credit memo, or refund receipt"
},
{
"name": "Estimates: Create",
"description": "Create an estimate with bounded item and description lines"
},
{
"name": "Estimates: Update",
"description": "Sparse-update an estimate using its current sync token"
},
{
"name": "Invoices: Create",
"description": "Create an invoice without emailing or collecting payment"
},
{
"name": "Invoices: Update",
"description": "Sparse-update an invoice using its current sync token"
},
{
"name": "Invoices: Void",
"description": "Void an invoice after explicit confirmation"
},
{
"name": "Sales Receipts: Create",
"description": "Create a sales receipt for a completed customer sale"
},
{
"name": "Sales Receipts: Update",
"description": "Sparse-update a sales receipt using its current sync token"
},
{
"name": "Customer Payments: Create",
"description": "Record a customer payment with optional bounded invoice allocations"
},
{
"name": "Customer Payments: Update",
"description": "Sparse-update a customer payment using its current sync token"
},
{
"name": "Customer Payments: Void",
"description": "Void a customer payment after explicit confirmation"
},
{
"name": "Credit Memos: Create",
"description": "Create a customer credit memo with bounded sales lines"
},
{
"name": "Credit Memos: Update",
"description": "Sparse-update a credit memo using its current sync token"
},
{
"name": "Refund Receipts: Create",
"description": "Create a customer refund receipt against a required deposit account"
},
{
"name": "Refund Receipts: Update",
"description": "Sparse-update a refund receipt using its current sync token"
},
{
"name": "Purchasing: List Purchase Orders",
"description": "List purchase orders in the connected QuickBooks Online company"
Expand All @@ -14566,7 +14626,7 @@
"description": "List bills in the connected QuickBooks Online company"
}
],
"operationCount": 10,
"operationCount": 25,
"triggers": [],
"triggerCount": 0,
"authType": "oauth",
Expand Down
15 changes: 12 additions & 3 deletions apps/sim/lib/quickbooks/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ export interface QuickBooksCompanyInfoEnvelope {
time?: string
}

export function assertQuickBooksCompanyInfo<T extends { Id?: unknown }>(candidate: unknown): T {
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
throw new Error('QuickBooks CompanyInfo response is missing a valid CompanyInfo object')
}
const id = (candidate as { Id?: unknown }).Id
if (typeof id !== 'string' || !id.trim()) {
throw new Error('QuickBooks CompanyInfo response is missing a valid company Id')
}
return candidate as T
}

function getQuickBooksTrackingId(headers: Headers): string | null {
return (
headers.get('intuit_tid') ?? headers.get('intuit-tid') ?? headers.get('x-request-id') ?? null
Expand Down Expand Up @@ -167,9 +178,7 @@ export async function fetchValidatedQuickBooksCompanyInfo(
)
}

if (!data.CompanyInfo || typeof data.CompanyInfo !== 'object') {
throw new Error('QuickBooks company validation response is missing CompanyInfo')
}
assertQuickBooksCompanyInfo(data.CompanyInfo)

return data
}
6 changes: 5 additions & 1 deletion apps/sim/lib/workflows/blocks/block-outputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function isConditionPrimitive(value: unknown): value is ConditionValue {
* Evaluates an output condition against subBlock values.
* Returns true if the condition is met and the output should be shown.
*/
function evaluateOutputCondition(
export function evaluateOutputCondition(
condition: OutputCondition,
subBlocks: Record<string, SubBlockWithValue> | undefined
): boolean {
Expand Down Expand Up @@ -93,6 +93,10 @@ function evaluateOutputCondition(
matches = matches && andMatches
}

if (condition.or) {
matches = matches || evaluateOutputCondition(condition.or, subBlocks)
}

return matches
}

Expand Down
113 changes: 113 additions & 0 deletions apps/sim/tools/quickbooks/create_credit_memo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/lib/quickbooks/client'
import { ErrorExtractorId } from '@/tools/error-extractors'
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
import type {
QuickBooksCreateCreditMemoParams,
QuickBooksMutationResponse,
QuickBooksSalesTransaction,
} from '@/tools/quickbooks/types'
import {
QUICKBOOKS_MUTATION_OUTPUTS,
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
} from '@/tools/quickbooks/types'
import {
addQuickBooksRequestId,
buildQuickBooksEntityUrl,
getQuickBooksToolHeaders,
transformQuickBooksMutationResponse,
} from '@/tools/quickbooks/utils'
import type { ToolConfig } from '@/tools/types'

export const quickbooksCreateCreditMemoTool: ToolConfig<
QuickBooksCreateCreditMemoParams,
QuickBooksMutationResponse<QuickBooksSalesTransaction>
> = {
id: 'quickbooks_create_credit_memo',
name: 'QuickBooks Create Credit Memo',
description: 'Create a customer credit memo with bounded sales lines',
version: '1.0.0',
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'QuickBooks OAuth access token',
},
realmId: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'QuickBooks company ID derived from the connected credential',
},
customerId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Customer receiving the credit memo',
},
lines: {
type: 'json',
required: true,
visibility: 'user-or-llm',
description: 'Bounded item and description lines',
},
transactionDate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Credit memo date in YYYY-MM-DD format',
},
documentNumber: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional credit memo number',
},
privateNote: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Internal credit memo note',
},
customerMemo: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Customer-facing credit memo memo',
},
requestId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional Intuit idempotency request ID, up to 50 characters',
},
},
oauth: {
required: true,
provider: 'quickbooks',
requiredScopes: ['com.intuit.quickbooks.accounting'],
},
errorExtractor: ErrorExtractorId.QUICKBOOKS_FAULT,
request: {
url: (params) =>
addQuickBooksRequestId(
buildQuickBooksEntityUrl(params.realmId, 'creditmemo'),
params.requestId
).toString(),
method: 'POST',
headers: (params) => getQuickBooksToolHeaders(params.accessToken, 'application/json'),
body: (params) => buildQuickBooksCreateSalesDocumentBody(params),
retry: { enabled: false },
maxResponseBytes: QUICKBOOKS_MAX_RESPONSE_BYTES,
},
transformResponse: (response) =>
transformQuickBooksMutationResponse<QuickBooksSalesTransaction>(response, 'CreditMemo'),
outputs: {
record: {
type: 'json',
description: 'Created native QuickBooks CreditMemo',
properties: QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
},
...QUICKBOOKS_MUTATION_OUTPUTS,
},
}
13 changes: 12 additions & 1 deletion apps/sim/tools/quickbooks/create_customer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
QUICKBOOKS_MUTATION_OUTPUTS,
} from '@/tools/quickbooks/types'
import {
addQuickBooksRequestId,
buildQuickBooksEntityUrl,
getQuickBooksToolHeaders,
optionalQuickBooksString,
Expand Down Expand Up @@ -96,6 +97,12 @@ export const quickbooksCreateCustomerTool: ToolConfig<
visibility: 'user-or-llm',
description: 'Whether sales to this customer are taxable',
},
requestId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Optional Intuit idempotency request ID, up to 50 characters',
},
},
oauth: {
required: true,
Expand All @@ -104,7 +111,11 @@ export const quickbooksCreateCustomerTool: ToolConfig<
},
errorExtractor: ErrorExtractorId.QUICKBOOKS_FAULT,
request: {
url: (params) => buildQuickBooksEntityUrl(params.realmId, 'customer').toString(),
url: (params) =>
addQuickBooksRequestId(
buildQuickBooksEntityUrl(params.realmId, 'customer'),
params.requestId
).toString(),
method: 'POST',
headers: (params) => getQuickBooksToolHeaders(params.accessToken, 'application/json'),
body: (params) =>
Expand Down
Loading