Skip to content

Commit 454309d

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(quickbooks): correct document schemas and upload bytes
1 parent 4699af8 commit 454309d

5 files changed

Lines changed: 95 additions & 3 deletions

File tree

apps/sim/app/api/tools/quickbooks/add-attachment/route.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,16 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
120120
)
121121
formData.append(
122122
'file_content_01',
123-
new Blob([new Uint8Array(downloaded.buffer)], { type: mimeType }),
123+
new Blob(
124+
[
125+
new Uint8Array(
126+
downloaded.buffer.buffer as ArrayBuffer,
127+
downloaded.buffer.byteOffset,
128+
downloaded.buffer.byteLength
129+
),
130+
],
131+
{ type: mimeType }
132+
),
124133
resolvedName
125134
)
126135
request.signal.throwIfAborted()

apps/sim/app/api/tools/quickbooks/documents.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,34 @@ describe('QuickBooks document API routes', () => {
269269
expect(mockFetch).toHaveBeenCalledTimes(1)
270270
})
271271

272+
it('uploads only the visible bytes from a sliced storage buffer', async () => {
273+
const backing = Buffer.from('before-visible-after')
274+
const visible = backing.subarray('before-'.length, 'before-visible'.length)
275+
mockDownloadServableFileFromStorage.mockResolvedValueOnce({
276+
buffer: visible,
277+
contentType: 'application/pdf',
278+
})
279+
mockFetch.mockResolvedValueOnce(
280+
Response.json({ AttachableResponse: [{ Attachable: { Id: '11' } }] })
281+
)
282+
283+
const response = await addAttachment(
284+
createMockRequest('POST', {
285+
...auth,
286+
attachmentKind: 'file',
287+
targetType: 'bill',
288+
targetId: '88',
289+
file: attachmentFile,
290+
})
291+
)
292+
293+
expect(response.status).toBe(200)
294+
expect(mockFetch).toHaveBeenCalledTimes(1)
295+
const formData = mockFetch.mock.calls[0][1].body as FormData
296+
const filePart = formData.get('file_content_01') as Blob
297+
expect(Buffer.from(await filePart.arrayBuffer()).toString()).toBe('visible')
298+
})
299+
272300
it('rejects an unauthorized workspace file before storage or Intuit access', async () => {
273301
mockAssertToolFileAccess.mockResolvedValueOnce(
274302
Response.json({ success: false, error: 'Forbidden' }, { status: 403 })

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
QuickBooksEmailTransactionParams,
1919
QuickBooksReadAttachmentsParams,
2020
} from '@/tools/quickbooks/types'
21+
import { QUICKBOOKS_EMAILABLE_TRANSACTION_PROPERTIES } from '@/tools/quickbooks/types'
2122

2223
const auth = { accessToken: 'access-token', realmId: '123456789' }
2324

@@ -88,6 +89,31 @@ describe('QuickBooks document tools', () => {
8889
},
8990
})
9091
})
92+
93+
it('advertises one optional sales and purchasing transaction output superset', () => {
94+
const record = quickbooksEmailTransactionTool.outputs?.record
95+
expect(record?.properties).toBe(QUICKBOOKS_EMAILABLE_TRANSACTION_PROPERTIES)
96+
expect(record?.properties).toMatchObject({
97+
CustomerRef: { optional: true },
98+
ExpirationDate: { optional: true },
99+
VendorRef: { optional: true },
100+
APAccountRef: { optional: true },
101+
POStatus: { optional: true },
102+
LinkedTxn: { optional: true },
103+
})
104+
expect(record?.properties?.Line).toMatchObject({
105+
optional: true,
106+
items: {
107+
properties: {
108+
SalesItemLineDetail: { optional: true },
109+
AccountBasedExpenseLineDetail: { optional: true },
110+
ItemBasedExpenseLineDetail: { optional: true },
111+
},
112+
},
113+
})
114+
expect(record?.properties?.Id.optional).not.toBe(true)
115+
expect(record?.properties?.CustomerRef.optional).toBe(true)
116+
})
91117
})
92118

93119
describe('QuickBooks attachment metadata reads', () => {

apps/sim/tools/quickbooks/email_transaction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
QuickBooksEmailTransactionResponse,
1414
QuickBooksTransaction,
1515
} from '@/tools/quickbooks/types'
16-
import { QUICKBOOKS_SALES_TRANSACTION_PROPERTIES } from '@/tools/quickbooks/types'
16+
import { QUICKBOOKS_EMAILABLE_TRANSACTION_PROPERTIES } from '@/tools/quickbooks/types'
1717
import { parseQuickBooksJson, requiredQuickBooksString } from '@/tools/quickbooks/utils'
1818
import type { ToolConfig } from '@/tools/types'
1919

@@ -123,7 +123,7 @@ export const quickbooksEmailTransactionTool: ToolConfig<
123123
type: 'json',
124124
description: 'Native QuickBooks transaction returned after sending',
125125
optional: true,
126-
properties: QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
126+
properties: QUICKBOOKS_EMAILABLE_TRANSACTION_PROPERTIES,
127127
},
128128
time: {
129129
type: 'string',

apps/sim/tools/quickbooks/types.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,6 +1753,35 @@ export const QUICKBOOKS_PURCHASING_TRANSACTION_PROPERTIES: Record<string, Output
17531753
},
17541754
}
17551755

1756+
export const QUICKBOOKS_EMAILABLE_TRANSACTION_PROPERTIES: Record<string, OutputProperty> = {
1757+
...QUICKBOOKS_SALES_TRANSACTION_PROPERTIES,
1758+
...QUICKBOOKS_PURCHASING_TRANSACTION_PROPERTIES,
1759+
Id: { type: 'string', description: 'QuickBooks transaction ID' },
1760+
DueDate: { type: 'string', description: 'Transaction due date', optional: true },
1761+
POStatus: { type: 'string', description: 'Purchase order status', optional: true },
1762+
Line: {
1763+
type: 'array',
1764+
description: 'Native QuickBooks sales or purchasing transaction lines',
1765+
optional: true,
1766+
items: {
1767+
type: 'json',
1768+
properties: {
1769+
...QUICKBOOKS_PURCHASING_LINE_PROPERTIES,
1770+
SalesItemLineDetail: {
1771+
type: 'json',
1772+
description: 'Native QuickBooks sales item line details',
1773+
optional: true,
1774+
},
1775+
DescriptionLineDetail: {
1776+
type: 'json',
1777+
description: 'Native QuickBooks description line details',
1778+
optional: true,
1779+
},
1780+
},
1781+
},
1782+
},
1783+
}
1784+
17561785
export const QUICKBOOKS_ACCOUNTING_TRANSACTION_PROPERTIES: Record<string, OutputProperty> = {
17571786
Id: { type: 'string', description: 'QuickBooks accounting transaction ID' },
17581787
SyncToken: { type: 'string', description: 'Current transaction sync token', optional: true },

0 commit comments

Comments
 (0)