Skip to content

Commit 2b4c706

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
feat(quickbooks): link bills to purchase order lines
1 parent d15b309 commit 2b4c706

5 files changed

Lines changed: 695 additions & 67 deletions

File tree

apps/sim/blocks/blocks/quickbooks.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from '@/tools/quickbooks/accounting_utils'
99
import {
1010
parseQuickBooksBillAllocations,
11+
parseQuickBooksBillLines,
1112
parseQuickBooksPurchasingLines,
1213
} from '@/tools/quickbooks/purchasing_utils'
1314
import {
@@ -742,7 +743,8 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
742743
title: 'Expense Lines (JSON)',
743744
type: 'code',
744745
language: 'json',
745-
placeholder: '[{"lineType":"account","amount":100,"accountId":"7","description":"Supplies"}]',
746+
placeholder:
747+
'[{"lineType":"account","amount":100,"accountId":"7","description":"Supplies","purchaseOrderId":"123","purchaseOrderLineId":"1"}]',
746748
condition: {
747749
field: 'operation',
748750
value: [
@@ -764,7 +766,7 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
764766
wandConfig: {
765767
enabled: true,
766768
prompt:
767-
'Generate a JSON array of QuickBooks purchasing lines. Use account lines with lineType account, positive amount, accountId, and optional description; or item lines with lineType item, positive amount, itemId, and optional description, positive quantity, and positive unitPrice. When quantity and unitPrice are both present, amount must equal their product. Return ONLY the JSON array - no explanations, no extra text.',
769+
'Generate a JSON array of QuickBooks purchasing lines. Use account lines with lineType account, positive amount, accountId, and optional description; or item lines with lineType item, positive amount, itemId, and optional description, positive quantity, and positive unitPrice. When quantity and unitPrice are both present, amount must equal their product. For Create Bill only, a line may include both purchaseOrderId and purchaseOrderLineId to request an explicit Purchase Order line link; always supply both or neither. Return ONLY the JSON array - no explanations, no extra text.',
768770
},
769771
},
770772
{
@@ -1328,7 +1330,9 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
13281330
: undefined,
13291331
lines:
13301332
isCreate && (isPurchaseOrder || isBill || isVendorCredit || isPurchase)
1331-
? parseQuickBooksPurchasingLines(params.purchasingLines)
1333+
? isBill
1334+
? parseQuickBooksBillLines(params.purchasingLines)
1335+
: parseQuickBooksPurchasingLines(params.purchasingLines)
13321336
: undefined,
13331337
totalAmount:
13341338
isCreate && isBillPayment
@@ -1516,7 +1520,11 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
15161520
expenseAccountId: { type: 'string', description: 'Item expense account ID' },
15171521
activeStatus: { type: 'string', description: 'Entity active-status change' },
15181522
lines: { type: 'json', description: 'Bounded item and description sales lines' },
1519-
purchasingLines: { type: 'json', description: 'Bounded purchasing expense lines' },
1523+
purchasingLines: {
1524+
type: 'json',
1525+
description:
1526+
'Bounded purchasing expense lines; Create Bill lines may include paired Purchase Order and line IDs',
1527+
},
15201528
journalLines: { type: 'json', description: 'Bounded balanced journal-entry lines' },
15211529
depositLines: { type: 'json', description: 'Bounded account-based deposit lines' },
15221530
totalAmount: { type: 'number', description: 'Customer or Bill payment total' },
@@ -1638,6 +1646,34 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
16381646
description: 'True when QuickBooks successfully voided the transaction',
16391647
condition: { field: 'operation', value: [...SALES_VOID_OPERATIONS] },
16401648
},
1649+
linkingRequested: {
1650+
type: 'boolean',
1651+
description: 'Whether Create Bill requested any Purchase Order line links',
1652+
condition: { field: 'operation', value: 'quickbooks_create_bill' },
1653+
},
1654+
linkingSucceeded: {
1655+
type: 'boolean',
1656+
description:
1657+
'Whether QuickBooks returned every requested Purchase Order line link; null when no links were requested',
1658+
condition: { field: 'operation', value: 'quickbooks_create_bill' },
1659+
},
1660+
linkedLines: {
1661+
type: 'array',
1662+
description:
1663+
'Confirmed Purchase Order links as [{purchaseOrderId, purchaseOrderLineId, billLineId}]',
1664+
condition: { field: 'operation', value: 'quickbooks_create_bill' },
1665+
},
1666+
missingLinks: {
1667+
type: 'array',
1668+
description:
1669+
'Requested links omitted by QuickBooks as [{purchaseOrderId, purchaseOrderLineId}]',
1670+
condition: { field: 'operation', value: 'quickbooks_create_bill' },
1671+
},
1672+
linkingWarning: {
1673+
type: 'string',
1674+
description: 'Warning that QuickBooks created the Bill without every requested link',
1675+
condition: { field: 'operation', value: 'quickbooks_create_bill' },
1676+
},
16411677
time: {
16421678
type: 'string',
16431679
description: 'QuickBooks response timestamp',
@@ -1734,7 +1770,7 @@ export const QuickBooksBlockMeta = {
17341770
icon: QuickBooksIcon,
17351771
title: 'QuickBooks bill entry and payment',
17361772
prompt:
1737-
'Build a controlled workflow that creates a standalone QuickBooks bill from approved expense lines, stores its ID and sync token, and records a separately approved partial or multi-Bill payment.',
1773+
'Build a controlled workflow that reads an approved Purchase Order by ID, captures its Line IDs, creates a QuickBooks Bill with explicit PO-line mappings, checks linkingSucceeded and missingLinks, and records a separately approved payment only after reviewing the created Bill.',
17381774
modules: ['tables', 'agent', 'workflows'],
17391775
category: 'operations',
17401776
tags: ['finance', 'payments', 'payables'],
@@ -1788,9 +1824,10 @@ export const QuickBooksBlockMeta = {
17881824
},
17891825
{
17901826
name: 'record-quickbooks-payables',
1791-
description: 'Create standalone bills and record bounded payments to approved Bill IDs.',
1827+
description:
1828+
'Create standalone or PO-linked bills and record bounded payments to approved Bill IDs.',
17921829
content:
1793-
'# Record QuickBooks Payables\n\n## Steps\n1. Validate the vendor, expense lines, and optional A/P account.\n2. Use Create Bill and store the returned ID and sync token.\n3. When payment is separately approved, use Create Bill Payment with bounded Bill allocations whose amounts equal the payment total.\n\n## Output\nReturn the native Bill or BillPayment and identifiers. Never create a payment implicitly.',
1830+
'# Record QuickBooks Payables\n\n## Steps\n1. Validate the vendor, expense lines, and optional A/P account.\n2. For PO-linked billing, use Read Purchasing Transactions by ID and copy each approved Purchase Order `Line[].Id` into the matching Create Bill line with its PO ID.\n3. Use Create Bill, store its ID and sync token, and inspect `linkingSucceeded` and `missingLinks`; QuickBooks may create the Bill while omitting an invalid or unavailable link.\n4. When payment is separately approved, use Create Bill Payment with bounded Bill allocations whose amounts equal the payment total.\n\n## Output\nAlways return the created Bill ID and linkage result. Never imply that a missing link prevented Bill creation, and never create a payment implicitly.',
17941831
},
17951832
{
17961833
name: 'record-quickbooks-purchases-and-vendor-credits',

apps/sim/tools/quickbooks/create_bill.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import { buildQuickBooksCreateBillBody } from '@/tools/quickbooks/purchasing_utils'
3+
import {
4+
buildQuickBooksCreateBillBody,
5+
verifyQuickBooksBillLinks,
6+
} from '@/tools/quickbooks/purchasing_utils'
47
import type {
58
QuickBooksCreateBillParams,
6-
QuickBooksMutationResponse,
9+
QuickBooksCreateBillResponse,
710
QuickBooksPurchasingTransaction,
811
} from '@/tools/quickbooks/types'
912
import {
13+
QUICKBOOKS_CREATE_BILL_LINK_OUTPUTS,
1014
QUICKBOOKS_MUTATION_OUTPUTS,
1115
QUICKBOOKS_PURCHASING_TRANSACTION_PROPERTIES,
1216
} from '@/tools/quickbooks/types'
@@ -20,11 +24,11 @@ import type { ToolConfig } from '@/tools/types'
2024

2125
export const quickbooksCreateBillTool: ToolConfig<
2226
QuickBooksCreateBillParams,
23-
QuickBooksMutationResponse<QuickBooksPurchasingTransaction>
27+
QuickBooksCreateBillResponse
2428
> = {
2529
id: 'quickbooks_create_bill',
2630
name: 'QuickBooks Create Bill',
27-
description: 'Create a vendor bill without paying it',
31+
description: 'Create a vendor bill with optional Purchase Order line links without paying it',
2832
version: '1.0.0',
2933
params: {
3034
accessToken: {
@@ -49,7 +53,8 @@ export const quickbooksCreateBillTool: ToolConfig<
4953
type: 'json',
5054
required: true,
5155
visibility: 'user-or-llm',
52-
description: 'Bounded account-based or item-based expense lines',
56+
description:
57+
'Bounded account-based or item-based expense lines with optional paired Purchase Order and line IDs',
5358
},
5459
apAccountId: {
5560
type: 'string',
@@ -103,14 +108,31 @@ export const quickbooksCreateBillTool: ToolConfig<
103108
retry: { enabled: false },
104109
maxResponseBytes: QUICKBOOKS_MAX_RESPONSE_BYTES,
105110
},
106-
transformResponse: (r) =>
107-
transformQuickBooksMutationResponse<QuickBooksPurchasingTransaction>(r, 'Bill'),
111+
transformResponse: async (response, params) => {
112+
if (!params) throw new Error('QuickBooks Create Bill parameters are required')
113+
const transformed = await transformQuickBooksMutationResponse<QuickBooksPurchasingTransaction>(
114+
response,
115+
'Bill'
116+
)
117+
return {
118+
...transformed,
119+
output: {
120+
...transformed.output,
121+
...verifyQuickBooksBillLinks(
122+
transformed.output.record,
123+
params.lines,
124+
transformed.output.recordId
125+
),
126+
},
127+
}
128+
},
108129
outputs: {
109130
record: {
110131
type: 'json',
111132
description: 'Created native QuickBooks Bill',
112133
properties: QUICKBOOKS_PURCHASING_TRANSACTION_PROPERTIES,
113134
},
114135
...QUICKBOOKS_MUTATION_OUTPUTS,
136+
...QUICKBOOKS_CREATE_BILL_LINK_OUTPUTS,
115137
},
116138
}

0 commit comments

Comments
 (0)