Skip to content

Commit ad88f00

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(quickbooks): validate calculated sales amounts
1 parent 62117d9 commit ad88f00

11 files changed

Lines changed: 65 additions & 40 deletions

File tree

apps/docs/content/docs/en/integrations/quickbooks.mdx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,8 @@ List or read one account, customer, vendor, item, or employee
188188
|`InvStartDate` | string | Inventory tracking start date |
189189
|`PrimaryAddr` | json | Employee primary address |
190190
|`BillableTime` | boolean | Whether employee time is billable |
191-
| `startPosition` | number | One-based position of the first item in this response |
192-
| `maxResults` | number | Actual number of items reported for this response |
191+
| `startPosition` | number | One-based position of the first record in this page |
192+
| `maxResults` | number | Actual number of records returned in this page |
193193
| `nextStartPosition` | number | Position to use when explicitly requesting the next page |
194194
| `hasMore` | boolean | Conservative indication that another page may exist |
195195
| `time` | string | QuickBooks response timestamp |
@@ -449,15 +449,14 @@ Create a Service or Non-inventory item in QuickBooks Online
449449

450450
### `quickbooks_update_item`
451451

452-
Sparse-update a Service or Non-inventory item in QuickBooks Online
452+
Sparse-update supported fields on an item without changing its type
453453

454454
#### Input
455455

456456
| Parameter | Type | Required | Description |
457457
| --------- | ---- | -------- | ----------- |
458458
| `itemId` | string | Yes | ID of the item to update |
459459
| `syncToken` | string | Yes | Current item sync token |
460-
| `itemType` | string | Yes | Current item type: service or non_inventory |
461460
| `name` | string | No | Replacement item name |
462461
| `incomeAccountId` | string | No | Replacement income account ID |
463462
| `description` | string | No | Replacement sales description |

apps/sim/blocks/blocks/quickbooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ export const QuickBooksBlock: BlockConfig<QuickBooksResponse> = {
573573
wandConfig: {
574574
enabled: true,
575575
prompt:
576-
'Generate a JSON array of QuickBooks sales lines. Use item lines with lineType, positive amount, itemId, and optional description, quantity, unitPrice, and serviceDate; or description lines with lineType and description. Return ONLY the JSON array - no explanations, no extra text.',
576+
'Generate a JSON array of QuickBooks sales lines. Use item lines with lineType, positive amount, itemId, and optional description, positive quantity, positive unitPrice, and serviceDate. When quantity and unitPrice are both present, amount must equal quantity multiplied by unitPrice. Use description lines with lineType and description. Return ONLY the JSON array - no explanations, no extra text.',
577577
generationType: 'json-object',
578578
},
579579
},

apps/sim/tools/quickbooks/create_credit_memo.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreateSalesDocumentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateCreditMemoParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/create_customer_payment.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreatePaymentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreatePaymentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateCustomerPaymentParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/create_estimate.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreateSalesDocumentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateEstimateParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/create_invoice.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreateSalesDocumentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateInvoiceParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/create_refund_receipt.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreateSalesDocumentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateRefundReceiptParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/create_sales_receipt.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { ErrorExtractorId } from '@/tools/error-extractors'
22
import { QUICKBOOKS_MAX_RESPONSE_BYTES } from '@/tools/quickbooks/client'
3-
import {
4-
addQuickBooksRequestId,
5-
buildQuickBooksCreateSalesDocumentBody,
6-
} from '@/tools/quickbooks/sales_utils'
3+
import { buildQuickBooksCreateSalesDocumentBody } from '@/tools/quickbooks/sales_utils'
74
import type {
85
QuickBooksCreateSalesReceiptParams,
96
QuickBooksMutationResponse,
@@ -14,6 +11,7 @@ import {
1411
QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1512
} from '@/tools/quickbooks/types'
1613
import {
14+
addQuickBooksRequestId,
1715
buildQuickBooksEntityUrl,
1816
getQuickBooksToolHeaders,
1917
transformQuickBooksMutationResponse,

apps/sim/tools/quickbooks/quickbooks.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest'
44
import { evaluateOutputCondition } from '@/lib/workflows/blocks/block-outputs'
55
import { evaluateSubBlockCondition } from '@/lib/workflows/subblocks/visibility'
66
import { QuickBooksBlock } from '@/blocks/blocks/quickbooks'
7-
import {
8-
fetchValidatedQuickBooksCompanyInfo,
9-
getQuickBooksEnvironment,
10-
getQuickBooksUserInfoUrl,
11-
QUICKBOOKS_MAX_RESPONSE_BYTES,
12-
} from '@/tools/quickbooks/client'
137
import {
148
quickbooksCreateCreditMemoTool,
159
quickbooksCreateCustomerPaymentTool,
@@ -27,6 +21,12 @@ import {
2721
quickbooksVoidCustomerPaymentTool,
2822
quickbooksVoidInvoiceTool,
2923
} from '@/tools/quickbooks'
24+
import {
25+
fetchValidatedQuickBooksCompanyInfo,
26+
getQuickBooksEnvironment,
27+
getQuickBooksUserInfoUrl,
28+
QUICKBOOKS_MAX_RESPONSE_BYTES,
29+
} from '@/tools/quickbooks/client'
3030
import { quickbooksCreateCustomerTool } from '@/tools/quickbooks/create_customer'
3131
import { quickbooksCreateItemTool } from '@/tools/quickbooks/create_item'
3232
import { quickbooksCreateVendorTool } from '@/tools/quickbooks/create_vendor'

apps/sim/tools/quickbooks/sales.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,32 @@ describe('QuickBooks sales document validation and bodies', () => {
191191
expect(() => parseQuickBooksSalesLines('[{"lineType":"item","amount":1,"itemId":7}]')).toThrow(
192192
'itemId must be a string'
193193
)
194+
expect(() =>
195+
parseQuickBooksSalesLines('[{"lineType":"item","amount":10,"itemId":"7","quantity":0}]')
196+
).toThrow('quantity must be a positive finite number')
197+
expect(() =>
198+
parseQuickBooksSalesLines('[{"lineType":"item","amount":10,"itemId":"7","unitPrice":-1}]')
199+
).toThrow('unitPrice must be a positive finite number')
200+
expect(() =>
201+
parseQuickBooksSalesLines(
202+
'[{"lineType":"item","amount":10,"itemId":"7","quantity":2,"unitPrice":6}]'
203+
)
204+
).toThrow('amount must equal quantity multiplied by unitPrice')
205+
expect(
206+
parseQuickBooksSalesLines(
207+
'[{"lineType":"item","amount":0.02,"itemId":"7","quantity":0.1,"unitPrice":0.2}]'
208+
)
209+
).toEqual([
210+
{
211+
lineType: 'item',
212+
amount: 0.02,
213+
itemId: '7',
214+
description: undefined,
215+
quantity: 0.1,
216+
unitPrice: 0.2,
217+
serviceDate: undefined,
218+
},
219+
])
194220
expect(() =>
195221
parseQuickBooksSalesLines(
196222
'[{"lineType":"item","amount":1,"itemId":"7","serviceDate":"2026-02-30"}]'

0 commit comments

Comments
 (0)