@rv404/mcp-launchpad 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +29 -0
- package/README.md +248 -0
- package/dist/backends/clickup.d.ts +3 -0
- package/dist/backends/clickup.d.ts.map +1 -0
- package/dist/backends/clickup.js +1550 -0
- package/dist/backends/clickup.js.map +1 -0
- package/dist/backends/email.d.ts +9 -0
- package/dist/backends/email.d.ts.map +1 -0
- package/dist/backends/email.js +452 -0
- package/dist/backends/email.js.map +1 -0
- package/dist/backends/firecrawl.d.ts +3 -0
- package/dist/backends/firecrawl.d.ts.map +1 -0
- package/dist/backends/firecrawl.js +297 -0
- package/dist/backends/firecrawl.js.map +1 -0
- package/dist/backends/gemini.d.ts +3 -0
- package/dist/backends/gemini.d.ts.map +1 -0
- package/dist/backends/gemini.js +702 -0
- package/dist/backends/gemini.js.map +1 -0
- package/dist/backends/github.d.ts +3 -0
- package/dist/backends/github.d.ts.map +1 -0
- package/dist/backends/github.js +2129 -0
- package/dist/backends/github.js.map +1 -0
- package/dist/backends/index.d.ts +2 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +27 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/kie.d.ts +3 -0
- package/dist/backends/kie.d.ts.map +1 -0
- package/dist/backends/kie.js +399 -0
- package/dist/backends/kie.js.map +1 -0
- package/dist/backends/n8n.d.ts +3 -0
- package/dist/backends/n8n.d.ts.map +1 -0
- package/dist/backends/n8n.js +414 -0
- package/dist/backends/n8n.js.map +1 -0
- package/dist/backends/notion.d.ts +3 -0
- package/dist/backends/notion.d.ts.map +1 -0
- package/dist/backends/notion.js +375 -0
- package/dist/backends/notion.js.map +1 -0
- package/dist/backends/quickbooks.d.ts +3 -0
- package/dist/backends/quickbooks.d.ts.map +1 -0
- package/dist/backends/quickbooks.js +2183 -0
- package/dist/backends/quickbooks.js.map +1 -0
- package/dist/backends/slack.d.ts +3 -0
- package/dist/backends/slack.d.ts.map +1 -0
- package/dist/backends/slack.js +1725 -0
- package/dist/backends/slack.js.map +1 -0
- package/dist/backends/youtube.d.ts +3 -0
- package/dist/backends/youtube.d.ts.map +1 -0
- package/dist/backends/youtube.js +936 -0
- package/dist/backends/youtube.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +150 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +36 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +283 -0
- package/dist/router.js.map +1 -0
- package/dist/types.d.ts +103 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +65 -0
- package/dist/types.js.map +1 -0
- package/lib/mcp-file-output/dist/index.d.ts +99 -0
- package/lib/mcp-file-output/dist/index.d.ts.map +1 -0
- package/lib/mcp-file-output/dist/index.js +215 -0
- package/lib/mcp-file-output/dist/index.js.map +1 -0
- package/lib/mcp-file-output/node_modules/@types/node/LICENSE +21 -0
- package/lib/mcp-file-output/node_modules/@types/node/README.md +15 -0
- package/lib/mcp-file-output/node_modules/@types/node/assert/strict.d.ts +8 -0
- package/lib/mcp-file-output/node_modules/@types/node/assert.d.ts +1062 -0
- package/lib/mcp-file-output/node_modules/@types/node/async_hooks.d.ts +605 -0
- package/lib/mcp-file-output/node_modules/@types/node/buffer.buffer.d.ts +471 -0
- package/lib/mcp-file-output/node_modules/@types/node/buffer.d.ts +1936 -0
- package/lib/mcp-file-output/node_modules/@types/node/child_process.d.ts +1475 -0
- package/lib/mcp-file-output/node_modules/@types/node/cluster.d.ts +577 -0
- package/lib/mcp-file-output/node_modules/@types/node/compatibility/disposable.d.ts +16 -0
- package/lib/mcp-file-output/node_modules/@types/node/compatibility/index.d.ts +9 -0
- package/lib/mcp-file-output/node_modules/@types/node/compatibility/indexable.d.ts +20 -0
- package/lib/mcp-file-output/node_modules/@types/node/compatibility/iterators.d.ts +21 -0
- package/lib/mcp-file-output/node_modules/@types/node/console.d.ts +452 -0
- package/lib/mcp-file-output/node_modules/@types/node/constants.d.ts +21 -0
- package/lib/mcp-file-output/node_modules/@types/node/crypto.d.ts +4590 -0
- package/lib/mcp-file-output/node_modules/@types/node/dgram.d.ts +597 -0
- package/lib/mcp-file-output/node_modules/@types/node/diagnostics_channel.d.ts +578 -0
- package/lib/mcp-file-output/node_modules/@types/node/dns/promises.d.ts +479 -0
- package/lib/mcp-file-output/node_modules/@types/node/dns.d.ts +871 -0
- package/lib/mcp-file-output/node_modules/@types/node/domain.d.ts +170 -0
- package/lib/mcp-file-output/node_modules/@types/node/events.d.ts +977 -0
- package/lib/mcp-file-output/node_modules/@types/node/fs/promises.d.ts +1270 -0
- package/lib/mcp-file-output/node_modules/@types/node/fs.d.ts +4375 -0
- package/lib/mcp-file-output/node_modules/@types/node/globals.d.ts +172 -0
- package/lib/mcp-file-output/node_modules/@types/node/globals.typedarray.d.ts +38 -0
- package/lib/mcp-file-output/node_modules/@types/node/http.d.ts +2049 -0
- package/lib/mcp-file-output/node_modules/@types/node/http2.d.ts +2631 -0
- package/lib/mcp-file-output/node_modules/@types/node/https.d.ts +578 -0
- package/lib/mcp-file-output/node_modules/@types/node/index.d.ts +93 -0
- package/lib/mcp-file-output/node_modules/@types/node/inspector.generated.d.ts +3966 -0
- package/lib/mcp-file-output/node_modules/@types/node/module.d.ts +539 -0
- package/lib/mcp-file-output/node_modules/@types/node/net.d.ts +1012 -0
- package/lib/mcp-file-output/node_modules/@types/node/os.d.ts +506 -0
- package/lib/mcp-file-output/node_modules/@types/node/package.json +140 -0
- package/lib/mcp-file-output/node_modules/@types/node/path.d.ts +200 -0
- package/lib/mcp-file-output/node_modules/@types/node/perf_hooks.d.ts +961 -0
- package/lib/mcp-file-output/node_modules/@types/node/process.d.ts +1957 -0
- package/lib/mcp-file-output/node_modules/@types/node/punycode.d.ts +117 -0
- package/lib/mcp-file-output/node_modules/@types/node/querystring.d.ts +152 -0
- package/lib/mcp-file-output/node_modules/@types/node/readline/promises.d.ts +162 -0
- package/lib/mcp-file-output/node_modules/@types/node/readline.d.ts +589 -0
- package/lib/mcp-file-output/node_modules/@types/node/repl.d.ts +430 -0
- package/lib/mcp-file-output/node_modules/@types/node/sea.d.ts +153 -0
- package/lib/mcp-file-output/node_modules/@types/node/stream/consumers.d.ts +38 -0
- package/lib/mcp-file-output/node_modules/@types/node/stream/promises.d.ts +90 -0
- package/lib/mcp-file-output/node_modules/@types/node/stream/web.d.ts +533 -0
- package/lib/mcp-file-output/node_modules/@types/node/stream.d.ts +1675 -0
- package/lib/mcp-file-output/node_modules/@types/node/string_decoder.d.ts +67 -0
- package/lib/mcp-file-output/node_modules/@types/node/test.d.ts +1787 -0
- package/lib/mcp-file-output/node_modules/@types/node/timers/promises.d.ts +108 -0
- package/lib/mcp-file-output/node_modules/@types/node/timers.d.ts +286 -0
- package/lib/mcp-file-output/node_modules/@types/node/tls.d.ts +1255 -0
- package/lib/mcp-file-output/node_modules/@types/node/trace_events.d.ts +197 -0
- package/lib/mcp-file-output/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +468 -0
- package/lib/mcp-file-output/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +34 -0
- package/lib/mcp-file-output/node_modules/@types/node/ts5.6/index.d.ts +93 -0
- package/lib/mcp-file-output/node_modules/@types/node/tty.d.ts +208 -0
- package/lib/mcp-file-output/node_modules/@types/node/url.d.ts +964 -0
- package/lib/mcp-file-output/node_modules/@types/node/util.d.ts +2331 -0
- package/lib/mcp-file-output/node_modules/@types/node/v8.d.ts +809 -0
- package/lib/mcp-file-output/node_modules/@types/node/vm.d.ts +1001 -0
- package/lib/mcp-file-output/node_modules/@types/node/wasi.d.ts +181 -0
- package/lib/mcp-file-output/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
- package/lib/mcp-file-output/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
- package/lib/mcp-file-output/node_modules/@types/node/web-globals/events.d.ts +97 -0
- package/lib/mcp-file-output/node_modules/@types/node/web-globals/fetch.d.ts +46 -0
- package/lib/mcp-file-output/node_modules/@types/node/worker_threads.d.ts +715 -0
- package/lib/mcp-file-output/node_modules/@types/node/zlib.d.ts +540 -0
- package/lib/mcp-file-output/package.json +19 -0
- package/lib/mcp-file-output/src/index.ts +309 -0
- package/lib/mcp-file-output/tsconfig.json +20 -0
- package/package.json +64 -0
|
@@ -0,0 +1,2183 @@
|
|
|
1
|
+
// QuickBooks API configuration
|
|
2
|
+
const IS_SANDBOX = process.env.QUICKBOOKS_SANDBOX === 'true';
|
|
3
|
+
const BASE_URL = IS_SANDBOX
|
|
4
|
+
? 'https://sandbox-quickbooks.api.intuit.com/v3/company'
|
|
5
|
+
: 'https://quickbooks.api.intuit.com/v3/company';
|
|
6
|
+
const TOKEN_URL = 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer';
|
|
7
|
+
// Environment variables
|
|
8
|
+
const CLIENT_ID = process.env.QUICKBOOKS_CLIENT_ID || '';
|
|
9
|
+
const CLIENT_SECRET = process.env.QUICKBOOKS_CLIENT_SECRET || '';
|
|
10
|
+
const REALM_ID = process.env.QUICKBOOKS_REALM_ID || '';
|
|
11
|
+
let refreshToken = process.env.QUICKBOOKS_REFRESH_TOKEN || '';
|
|
12
|
+
// Token cache
|
|
13
|
+
let accessToken = null;
|
|
14
|
+
let tokenExpiry = 0;
|
|
15
|
+
// API version
|
|
16
|
+
const MINOR_VERSION = '70';
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// AUTH & API HELPERS
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Refresh the OAuth access token using the refresh token
|
|
22
|
+
*/
|
|
23
|
+
async function getAccessToken() {
|
|
24
|
+
if (accessToken && Date.now() < tokenExpiry - 60000) {
|
|
25
|
+
return accessToken;
|
|
26
|
+
}
|
|
27
|
+
if (!CLIENT_ID || !CLIENT_SECRET || !refreshToken) {
|
|
28
|
+
throw new Error('QuickBooks credentials not configured. Set QUICKBOOKS_CLIENT_ID, QUICKBOOKS_CLIENT_SECRET, and QUICKBOOKS_REFRESH_TOKEN');
|
|
29
|
+
}
|
|
30
|
+
const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
|
|
31
|
+
const response = await fetch(TOKEN_URL, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'Authorization': `Basic ${credentials}`,
|
|
35
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
36
|
+
'Accept': 'application/json',
|
|
37
|
+
},
|
|
38
|
+
body: new URLSearchParams({
|
|
39
|
+
grant_type: 'refresh_token',
|
|
40
|
+
refresh_token: refreshToken,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
const errorText = await response.text();
|
|
45
|
+
if (response.status === 400 || response.status === 401) {
|
|
46
|
+
throw new Error(`QuickBooks auth failed: Refresh token may be expired or invalid. Re-authenticate at developer.intuit.com/app/developer/playground. Details: ${errorText}`);
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`QuickBooks token refresh failed (${response.status}): ${errorText}`);
|
|
49
|
+
}
|
|
50
|
+
const data = await response.json();
|
|
51
|
+
accessToken = data.access_token;
|
|
52
|
+
tokenExpiry = Date.now() + (data.expires_in * 1000);
|
|
53
|
+
if (data.refresh_token) {
|
|
54
|
+
refreshToken = data.refresh_token;
|
|
55
|
+
}
|
|
56
|
+
return accessToken;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Make an authenticated API request to QuickBooks
|
|
60
|
+
*/
|
|
61
|
+
async function qbRequest(endpoint, method = 'GET', body) {
|
|
62
|
+
const token = await getAccessToken();
|
|
63
|
+
if (!REALM_ID) {
|
|
64
|
+
throw new Error('QUICKBOOKS_REALM_ID not configured');
|
|
65
|
+
}
|
|
66
|
+
const url = `${BASE_URL}/${REALM_ID}/${endpoint}${endpoint.includes('?') ? '&' : '?'}minorversion=${MINOR_VERSION}`;
|
|
67
|
+
const response = await fetch(url, {
|
|
68
|
+
method,
|
|
69
|
+
headers: {
|
|
70
|
+
'Authorization': `Bearer ${token}`,
|
|
71
|
+
'Accept': 'application/json',
|
|
72
|
+
'Content-Type': 'application/json',
|
|
73
|
+
},
|
|
74
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
const errorText = await response.text();
|
|
78
|
+
if (response.status === 401) {
|
|
79
|
+
accessToken = null;
|
|
80
|
+
tokenExpiry = 0;
|
|
81
|
+
throw new Error(`QuickBooks auth error: ${errorText}`);
|
|
82
|
+
}
|
|
83
|
+
if (response.status === 429) {
|
|
84
|
+
throw new Error(`QuickBooks rate limit exceeded. Try again later.`);
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`QuickBooks API error (${response.status}): ${errorText}`);
|
|
87
|
+
}
|
|
88
|
+
return response.json();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Run a query against QuickBooks
|
|
92
|
+
*/
|
|
93
|
+
async function qbQuery(query) {
|
|
94
|
+
return qbRequest(`query?query=${encodeURIComponent(query)}`);
|
|
95
|
+
}
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// ACTION DEFINITIONS
|
|
98
|
+
// ============================================================================
|
|
99
|
+
const actions = [
|
|
100
|
+
// --------------------------------------------------------------------------
|
|
101
|
+
// COMPANY
|
|
102
|
+
// --------------------------------------------------------------------------
|
|
103
|
+
{
|
|
104
|
+
name: 'get_company_info',
|
|
105
|
+
description: 'Get company information and settings',
|
|
106
|
+
params: [],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'get_preferences',
|
|
110
|
+
description: 'Get company preferences and settings',
|
|
111
|
+
params: [],
|
|
112
|
+
},
|
|
113
|
+
// --------------------------------------------------------------------------
|
|
114
|
+
// CUSTOMERS
|
|
115
|
+
// --------------------------------------------------------------------------
|
|
116
|
+
{
|
|
117
|
+
name: 'list_customers',
|
|
118
|
+
description: 'List all customers',
|
|
119
|
+
params: [
|
|
120
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results (default: 100, max: 1000)' },
|
|
121
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position for pagination' },
|
|
122
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Filter by active status' },
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'get_customer',
|
|
127
|
+
description: 'Get a specific customer by ID',
|
|
128
|
+
params: [
|
|
129
|
+
{ name: 'customerId', type: 'string', required: true, description: 'The customer ID' },
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'create_customer',
|
|
134
|
+
description: 'Create a new customer',
|
|
135
|
+
params: [
|
|
136
|
+
{ name: 'displayName', type: 'string', required: true, description: 'Display name (must be unique)' },
|
|
137
|
+
{ name: 'companyName', type: 'string', required: false, description: 'Company name' },
|
|
138
|
+
{ name: 'givenName', type: 'string', required: false, description: 'First name' },
|
|
139
|
+
{ name: 'familyName', type: 'string', required: false, description: 'Last name' },
|
|
140
|
+
{ name: 'email', type: 'string', required: false, description: 'Primary email address' },
|
|
141
|
+
{ name: 'phone', type: 'string', required: false, description: 'Primary phone number' },
|
|
142
|
+
{ name: 'billingAddress', type: 'object', required: false, description: 'Billing address {Line1, City, CountrySubDivisionCode, PostalCode}' },
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: 'update_customer',
|
|
147
|
+
description: 'Update an existing customer',
|
|
148
|
+
params: [
|
|
149
|
+
{ name: 'customerId', type: 'string', required: true, description: 'The customer ID' },
|
|
150
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token (from get_customer)' },
|
|
151
|
+
{ name: 'displayName', type: 'string', required: false, description: 'Display name' },
|
|
152
|
+
{ name: 'companyName', type: 'string', required: false, description: 'Company name' },
|
|
153
|
+
{ name: 'givenName', type: 'string', required: false, description: 'First name' },
|
|
154
|
+
{ name: 'familyName', type: 'string', required: false, description: 'Last name' },
|
|
155
|
+
{ name: 'email', type: 'string', required: false, description: 'Primary email address' },
|
|
156
|
+
{ name: 'phone', type: 'string', required: false, description: 'Primary phone number' },
|
|
157
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Active status' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
// --------------------------------------------------------------------------
|
|
161
|
+
// INVOICES
|
|
162
|
+
// --------------------------------------------------------------------------
|
|
163
|
+
{
|
|
164
|
+
name: 'list_invoices',
|
|
165
|
+
description: 'List all invoices',
|
|
166
|
+
params: [
|
|
167
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results (default: 100, max: 1000)' },
|
|
168
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position for pagination' },
|
|
169
|
+
{ name: 'status', type: 'string', required: false, description: 'Filter by status: Paid, Unpaid, Overdue' },
|
|
170
|
+
{ name: 'customerId', type: 'string', required: false, description: 'Filter by customer ID' },
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'get_invoice',
|
|
175
|
+
description: 'Get a specific invoice by ID',
|
|
176
|
+
params: [
|
|
177
|
+
{ name: 'invoiceId', type: 'string', required: true, description: 'The invoice ID' },
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'create_invoice',
|
|
182
|
+
description: 'Create a new invoice',
|
|
183
|
+
params: [
|
|
184
|
+
{ name: 'customerId', type: 'string', required: true, description: 'Customer ID' },
|
|
185
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items [{itemId, quantity, amount, description}]' },
|
|
186
|
+
{ name: 'dueDate', type: 'string', required: false, description: 'Due date (YYYY-MM-DD)' },
|
|
187
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date (YYYY-MM-DD)' },
|
|
188
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note (not shown to customer)' },
|
|
189
|
+
{ name: 'customerMemo', type: 'string', required: false, description: 'Customer-facing memo' },
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'update_invoice',
|
|
194
|
+
description: 'Update an existing invoice',
|
|
195
|
+
params: [
|
|
196
|
+
{ name: 'invoiceId', type: 'string', required: true, description: 'The invoice ID' },
|
|
197
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token (from get_invoice)' },
|
|
198
|
+
{ name: 'lineItems', type: 'array', required: false, description: 'Array of line items' },
|
|
199
|
+
{ name: 'dueDate', type: 'string', required: false, description: 'Due date (YYYY-MM-DD)' },
|
|
200
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
201
|
+
{ name: 'customerMemo', type: 'string', required: false, description: 'Customer-facing memo' },
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'delete_invoice',
|
|
206
|
+
description: 'Delete an invoice',
|
|
207
|
+
params: [
|
|
208
|
+
{ name: 'invoiceId', type: 'string', required: true, description: 'The invoice ID' },
|
|
209
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
name: 'send_invoice',
|
|
214
|
+
description: 'Send an invoice via email',
|
|
215
|
+
params: [
|
|
216
|
+
{ name: 'invoiceId', type: 'string', required: true, description: 'The invoice ID' },
|
|
217
|
+
{ name: 'email', type: 'string', required: false, description: 'Email address (uses customer email if not specified)' },
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: 'void_invoice',
|
|
222
|
+
description: 'Void an invoice',
|
|
223
|
+
params: [
|
|
224
|
+
{ name: 'invoiceId', type: 'string', required: true, description: 'The invoice ID' },
|
|
225
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
// --------------------------------------------------------------------------
|
|
229
|
+
// ESTIMATES
|
|
230
|
+
// --------------------------------------------------------------------------
|
|
231
|
+
{
|
|
232
|
+
name: 'list_estimates',
|
|
233
|
+
description: 'List all estimates/quotes',
|
|
234
|
+
params: [
|
|
235
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
236
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
237
|
+
{ name: 'customerId', type: 'string', required: false, description: 'Filter by customer ID' },
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: 'get_estimate',
|
|
242
|
+
description: 'Get a specific estimate by ID',
|
|
243
|
+
params: [
|
|
244
|
+
{ name: 'estimateId', type: 'string', required: true, description: 'The estimate ID' },
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: 'create_estimate',
|
|
249
|
+
description: 'Create a new estimate/quote',
|
|
250
|
+
params: [
|
|
251
|
+
{ name: 'customerId', type: 'string', required: true, description: 'Customer ID' },
|
|
252
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items' },
|
|
253
|
+
{ name: 'expirationDate', type: 'string', required: false, description: 'Expiration date (YYYY-MM-DD)' },
|
|
254
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
255
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
256
|
+
{ name: 'customerMemo', type: 'string', required: false, description: 'Customer-facing memo' },
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: 'update_estimate',
|
|
261
|
+
description: 'Update an existing estimate',
|
|
262
|
+
params: [
|
|
263
|
+
{ name: 'estimateId', type: 'string', required: true, description: 'The estimate ID' },
|
|
264
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
265
|
+
{ name: 'lineItems', type: 'array', required: false, description: 'Array of line items' },
|
|
266
|
+
{ name: 'expirationDate', type: 'string', required: false, description: 'Expiration date' },
|
|
267
|
+
{ name: 'txnStatus', type: 'string', required: false, description: 'Status: Pending, Accepted, Closed, Rejected' },
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
name: 'delete_estimate',
|
|
272
|
+
description: 'Delete an estimate',
|
|
273
|
+
params: [
|
|
274
|
+
{ name: 'estimateId', type: 'string', required: true, description: 'The estimate ID' },
|
|
275
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
276
|
+
],
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'send_estimate',
|
|
280
|
+
description: 'Send an estimate via email',
|
|
281
|
+
params: [
|
|
282
|
+
{ name: 'estimateId', type: 'string', required: true, description: 'The estimate ID' },
|
|
283
|
+
{ name: 'email', type: 'string', required: false, description: 'Email address' },
|
|
284
|
+
],
|
|
285
|
+
},
|
|
286
|
+
// --------------------------------------------------------------------------
|
|
287
|
+
// PAYMENTS
|
|
288
|
+
// --------------------------------------------------------------------------
|
|
289
|
+
{
|
|
290
|
+
name: 'list_payments',
|
|
291
|
+
description: 'List all payments received',
|
|
292
|
+
params: [
|
|
293
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
294
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
295
|
+
{ name: 'customerId', type: 'string', required: false, description: 'Filter by customer ID' },
|
|
296
|
+
],
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: 'get_payment',
|
|
300
|
+
description: 'Get a specific payment by ID',
|
|
301
|
+
params: [
|
|
302
|
+
{ name: 'paymentId', type: 'string', required: true, description: 'The payment ID' },
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: 'create_payment',
|
|
307
|
+
description: 'Record a payment received',
|
|
308
|
+
params: [
|
|
309
|
+
{ name: 'customerId', type: 'string', required: true, description: 'Customer ID' },
|
|
310
|
+
{ name: 'totalAmt', type: 'number', required: true, description: 'Total payment amount' },
|
|
311
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Payment date (YYYY-MM-DD)' },
|
|
312
|
+
{ name: 'paymentMethodId', type: 'string', required: false, description: 'Payment method ID' },
|
|
313
|
+
{ name: 'depositToAccountId', type: 'string', required: false, description: 'Account to deposit to' },
|
|
314
|
+
{ name: 'invoiceIds', type: 'array', required: false, description: 'Invoice IDs to apply payment to' },
|
|
315
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: 'update_payment',
|
|
320
|
+
description: 'Update a payment',
|
|
321
|
+
params: [
|
|
322
|
+
{ name: 'paymentId', type: 'string', required: true, description: 'The payment ID' },
|
|
323
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
324
|
+
{ name: 'totalAmt', type: 'number', required: false, description: 'Total amount' },
|
|
325
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Payment date' },
|
|
326
|
+
],
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: 'delete_payment',
|
|
330
|
+
description: 'Delete a payment',
|
|
331
|
+
params: [
|
|
332
|
+
{ name: 'paymentId', type: 'string', required: true, description: 'The payment ID' },
|
|
333
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
334
|
+
],
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
name: 'void_payment',
|
|
338
|
+
description: 'Void a payment',
|
|
339
|
+
params: [
|
|
340
|
+
{ name: 'paymentId', type: 'string', required: true, description: 'The payment ID' },
|
|
341
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
// --------------------------------------------------------------------------
|
|
345
|
+
// SALES RECEIPTS
|
|
346
|
+
// --------------------------------------------------------------------------
|
|
347
|
+
{
|
|
348
|
+
name: 'list_sales_receipts',
|
|
349
|
+
description: 'List all sales receipts (immediate payments)',
|
|
350
|
+
params: [
|
|
351
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
352
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
353
|
+
],
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: 'get_sales_receipt',
|
|
357
|
+
description: 'Get a specific sales receipt',
|
|
358
|
+
params: [
|
|
359
|
+
{ name: 'salesReceiptId', type: 'string', required: true, description: 'The sales receipt ID' },
|
|
360
|
+
],
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
name: 'create_sales_receipt',
|
|
364
|
+
description: 'Create a sales receipt (sale with immediate payment)',
|
|
365
|
+
params: [
|
|
366
|
+
{ name: 'customerId', type: 'string', required: false, description: 'Customer ID (optional for cash sales)' },
|
|
367
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items' },
|
|
368
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
369
|
+
{ name: 'paymentMethodId', type: 'string', required: false, description: 'Payment method ID' },
|
|
370
|
+
{ name: 'depositToAccountId', type: 'string', required: false, description: 'Account to deposit to' },
|
|
371
|
+
],
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
name: 'delete_sales_receipt',
|
|
375
|
+
description: 'Delete a sales receipt',
|
|
376
|
+
params: [
|
|
377
|
+
{ name: 'salesReceiptId', type: 'string', required: true, description: 'The sales receipt ID' },
|
|
378
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
379
|
+
],
|
|
380
|
+
},
|
|
381
|
+
// --------------------------------------------------------------------------
|
|
382
|
+
// CREDIT MEMOS
|
|
383
|
+
// --------------------------------------------------------------------------
|
|
384
|
+
{
|
|
385
|
+
name: 'list_credit_memos',
|
|
386
|
+
description: 'List all credit memos',
|
|
387
|
+
params: [
|
|
388
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
389
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: 'get_credit_memo',
|
|
394
|
+
description: 'Get a specific credit memo',
|
|
395
|
+
params: [
|
|
396
|
+
{ name: 'creditMemoId', type: 'string', required: true, description: 'The credit memo ID' },
|
|
397
|
+
],
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
name: 'create_credit_memo',
|
|
401
|
+
description: 'Create a credit memo',
|
|
402
|
+
params: [
|
|
403
|
+
{ name: 'customerId', type: 'string', required: true, description: 'Customer ID' },
|
|
404
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items' },
|
|
405
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
406
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
407
|
+
],
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'delete_credit_memo',
|
|
411
|
+
description: 'Delete a credit memo',
|
|
412
|
+
params: [
|
|
413
|
+
{ name: 'creditMemoId', type: 'string', required: true, description: 'The credit memo ID' },
|
|
414
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
415
|
+
],
|
|
416
|
+
},
|
|
417
|
+
// --------------------------------------------------------------------------
|
|
418
|
+
// REFUND RECEIPTS
|
|
419
|
+
// --------------------------------------------------------------------------
|
|
420
|
+
{
|
|
421
|
+
name: 'list_refund_receipts',
|
|
422
|
+
description: 'List all refund receipts',
|
|
423
|
+
params: [
|
|
424
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
425
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
426
|
+
],
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'get_refund_receipt',
|
|
430
|
+
description: 'Get a specific refund receipt',
|
|
431
|
+
params: [
|
|
432
|
+
{ name: 'refundReceiptId', type: 'string', required: true, description: 'The refund receipt ID' },
|
|
433
|
+
],
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
name: 'create_refund_receipt',
|
|
437
|
+
description: 'Create a refund receipt',
|
|
438
|
+
params: [
|
|
439
|
+
{ name: 'customerId', type: 'string', required: true, description: 'Customer ID' },
|
|
440
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items' },
|
|
441
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
442
|
+
{ name: 'depositToAccountId', type: 'string', required: false, description: 'Account to refund from' },
|
|
443
|
+
],
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
name: 'delete_refund_receipt',
|
|
447
|
+
description: 'Delete a refund receipt',
|
|
448
|
+
params: [
|
|
449
|
+
{ name: 'refundReceiptId', type: 'string', required: true, description: 'The refund receipt ID' },
|
|
450
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
451
|
+
],
|
|
452
|
+
},
|
|
453
|
+
// --------------------------------------------------------------------------
|
|
454
|
+
// VENDORS
|
|
455
|
+
// --------------------------------------------------------------------------
|
|
456
|
+
{
|
|
457
|
+
name: 'list_vendors',
|
|
458
|
+
description: 'List all vendors',
|
|
459
|
+
params: [
|
|
460
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
461
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
462
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Filter by active status' },
|
|
463
|
+
],
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
name: 'get_vendor',
|
|
467
|
+
description: 'Get a specific vendor by ID',
|
|
468
|
+
params: [
|
|
469
|
+
{ name: 'vendorId', type: 'string', required: true, description: 'The vendor ID' },
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
name: 'create_vendor',
|
|
474
|
+
description: 'Create a new vendor',
|
|
475
|
+
params: [
|
|
476
|
+
{ name: 'displayName', type: 'string', required: true, description: 'Display name (must be unique)' },
|
|
477
|
+
{ name: 'companyName', type: 'string', required: false, description: 'Company name' },
|
|
478
|
+
{ name: 'givenName', type: 'string', required: false, description: 'First name' },
|
|
479
|
+
{ name: 'familyName', type: 'string', required: false, description: 'Last name' },
|
|
480
|
+
{ name: 'email', type: 'string', required: false, description: 'Primary email' },
|
|
481
|
+
{ name: 'phone', type: 'string', required: false, description: 'Primary phone' },
|
|
482
|
+
],
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
name: 'update_vendor',
|
|
486
|
+
description: 'Update an existing vendor',
|
|
487
|
+
params: [
|
|
488
|
+
{ name: 'vendorId', type: 'string', required: true, description: 'The vendor ID' },
|
|
489
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
490
|
+
{ name: 'displayName', type: 'string', required: false, description: 'Display name' },
|
|
491
|
+
{ name: 'email', type: 'string', required: false, description: 'Email' },
|
|
492
|
+
{ name: 'phone', type: 'string', required: false, description: 'Phone' },
|
|
493
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Active status' },
|
|
494
|
+
],
|
|
495
|
+
},
|
|
496
|
+
// --------------------------------------------------------------------------
|
|
497
|
+
// BILLS
|
|
498
|
+
// --------------------------------------------------------------------------
|
|
499
|
+
{
|
|
500
|
+
name: 'list_bills',
|
|
501
|
+
description: 'List all bills (vendor invoices)',
|
|
502
|
+
params: [
|
|
503
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
504
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
505
|
+
{ name: 'vendorId', type: 'string', required: false, description: 'Filter by vendor ID' },
|
|
506
|
+
{ name: 'status', type: 'string', required: false, description: 'Filter by status: Paid, Unpaid' },
|
|
507
|
+
],
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: 'get_bill',
|
|
511
|
+
description: 'Get a specific bill by ID',
|
|
512
|
+
params: [
|
|
513
|
+
{ name: 'billId', type: 'string', required: true, description: 'The bill ID' },
|
|
514
|
+
],
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
name: 'create_bill',
|
|
518
|
+
description: 'Create a new bill (vendor invoice)',
|
|
519
|
+
params: [
|
|
520
|
+
{ name: 'vendorId', type: 'string', required: true, description: 'Vendor ID' },
|
|
521
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items [{accountId, amount, description}]' },
|
|
522
|
+
{ name: 'dueDate', type: 'string', required: false, description: 'Due date (YYYY-MM-DD)' },
|
|
523
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
524
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
525
|
+
],
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: 'update_bill',
|
|
529
|
+
description: 'Update an existing bill',
|
|
530
|
+
params: [
|
|
531
|
+
{ name: 'billId', type: 'string', required: true, description: 'The bill ID' },
|
|
532
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
533
|
+
{ name: 'lineItems', type: 'array', required: false, description: 'Array of line items' },
|
|
534
|
+
{ name: 'dueDate', type: 'string', required: false, description: 'Due date' },
|
|
535
|
+
],
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
name: 'delete_bill',
|
|
539
|
+
description: 'Delete a bill',
|
|
540
|
+
params: [
|
|
541
|
+
{ name: 'billId', type: 'string', required: true, description: 'The bill ID' },
|
|
542
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
543
|
+
],
|
|
544
|
+
},
|
|
545
|
+
// --------------------------------------------------------------------------
|
|
546
|
+
// BILL PAYMENTS
|
|
547
|
+
// --------------------------------------------------------------------------
|
|
548
|
+
{
|
|
549
|
+
name: 'list_bill_payments',
|
|
550
|
+
description: 'List all bill payments',
|
|
551
|
+
params: [
|
|
552
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
553
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
554
|
+
],
|
|
555
|
+
},
|
|
556
|
+
{
|
|
557
|
+
name: 'get_bill_payment',
|
|
558
|
+
description: 'Get a specific bill payment',
|
|
559
|
+
params: [
|
|
560
|
+
{ name: 'billPaymentId', type: 'string', required: true, description: 'The bill payment ID' },
|
|
561
|
+
],
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
name: 'create_bill_payment',
|
|
565
|
+
description: 'Create a bill payment (pay a vendor bill)',
|
|
566
|
+
params: [
|
|
567
|
+
{ name: 'vendorId', type: 'string', required: true, description: 'Vendor ID' },
|
|
568
|
+
{ name: 'totalAmt', type: 'number', required: true, description: 'Total payment amount' },
|
|
569
|
+
{ name: 'payType', type: 'string', required: true, description: 'Payment type: Check or CreditCard' },
|
|
570
|
+
{ name: 'billIds', type: 'array', required: true, description: 'Bill IDs to pay' },
|
|
571
|
+
{ name: 'bankAccountId', type: 'string', required: false, description: 'Bank account ID (for Check)' },
|
|
572
|
+
{ name: 'creditCardAccountId', type: 'string', required: false, description: 'Credit card account ID (for CreditCard)' },
|
|
573
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Payment date' },
|
|
574
|
+
],
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
name: 'delete_bill_payment',
|
|
578
|
+
description: 'Delete a bill payment',
|
|
579
|
+
params: [
|
|
580
|
+
{ name: 'billPaymentId', type: 'string', required: true, description: 'The bill payment ID' },
|
|
581
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
582
|
+
],
|
|
583
|
+
},
|
|
584
|
+
// --------------------------------------------------------------------------
|
|
585
|
+
// EXPENSES / PURCHASES
|
|
586
|
+
// --------------------------------------------------------------------------
|
|
587
|
+
{
|
|
588
|
+
name: 'list_purchases',
|
|
589
|
+
description: 'List all purchases/expenses',
|
|
590
|
+
params: [
|
|
591
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
592
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
name: 'get_purchase',
|
|
597
|
+
description: 'Get a specific purchase/expense',
|
|
598
|
+
params: [
|
|
599
|
+
{ name: 'purchaseId', type: 'string', required: true, description: 'The purchase ID' },
|
|
600
|
+
],
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
name: 'create_expense',
|
|
604
|
+
description: 'Create an expense (cash/check/credit card purchase)',
|
|
605
|
+
params: [
|
|
606
|
+
{ name: 'paymentType', type: 'string', required: true, description: 'Payment type: Cash, Check, or CreditCard' },
|
|
607
|
+
{ name: 'accountId', type: 'string', required: true, description: 'Bank/Credit Card account ID' },
|
|
608
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of line items [{accountId, amount, description}]' },
|
|
609
|
+
{ name: 'vendorId', type: 'string', required: false, description: 'Vendor ID' },
|
|
610
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
611
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
612
|
+
],
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
name: 'delete_purchase',
|
|
616
|
+
description: 'Delete a purchase/expense',
|
|
617
|
+
params: [
|
|
618
|
+
{ name: 'purchaseId', type: 'string', required: true, description: 'The purchase ID' },
|
|
619
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
620
|
+
],
|
|
621
|
+
},
|
|
622
|
+
// --------------------------------------------------------------------------
|
|
623
|
+
// ITEMS (PRODUCTS/SERVICES)
|
|
624
|
+
// --------------------------------------------------------------------------
|
|
625
|
+
{
|
|
626
|
+
name: 'list_items',
|
|
627
|
+
description: 'List products and services',
|
|
628
|
+
params: [
|
|
629
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
630
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
631
|
+
{ name: 'type', type: 'string', required: false, description: 'Filter by type: Service, Inventory, NonInventory' },
|
|
632
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Filter by active status' },
|
|
633
|
+
],
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
name: 'get_item',
|
|
637
|
+
description: 'Get a specific item by ID',
|
|
638
|
+
params: [
|
|
639
|
+
{ name: 'itemId', type: 'string', required: true, description: 'The item ID' },
|
|
640
|
+
],
|
|
641
|
+
},
|
|
642
|
+
{
|
|
643
|
+
name: 'create_item',
|
|
644
|
+
description: 'Create a new item (product or service)',
|
|
645
|
+
params: [
|
|
646
|
+
{ name: 'name', type: 'string', required: true, description: 'Item name (must be unique)' },
|
|
647
|
+
{ name: 'type', type: 'string', required: true, description: 'Item type: Service, Inventory, or NonInventory' },
|
|
648
|
+
{ name: 'incomeAccountId', type: 'string', required: true, description: 'Income account ID' },
|
|
649
|
+
{ name: 'expenseAccountId', type: 'string', required: false, description: 'Expense account ID (for inventory)' },
|
|
650
|
+
{ name: 'unitPrice', type: 'number', required: false, description: 'Sales price' },
|
|
651
|
+
{ name: 'purchaseCost', type: 'number', required: false, description: 'Purchase cost' },
|
|
652
|
+
{ name: 'description', type: 'string', required: false, description: 'Sales description' },
|
|
653
|
+
{ name: 'purchaseDesc', type: 'string', required: false, description: 'Purchase description' },
|
|
654
|
+
{ name: 'qtyOnHand', type: 'number', required: false, description: 'Initial quantity (for inventory)' },
|
|
655
|
+
{ name: 'assetAccountId', type: 'string', required: false, description: 'Asset account (for inventory)' },
|
|
656
|
+
],
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
name: 'update_item',
|
|
660
|
+
description: 'Update an existing item',
|
|
661
|
+
params: [
|
|
662
|
+
{ name: 'itemId', type: 'string', required: true, description: 'The item ID' },
|
|
663
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
664
|
+
{ name: 'name', type: 'string', required: false, description: 'Item name' },
|
|
665
|
+
{ name: 'unitPrice', type: 'number', required: false, description: 'Sales price' },
|
|
666
|
+
{ name: 'purchaseCost', type: 'number', required: false, description: 'Purchase cost' },
|
|
667
|
+
{ name: 'description', type: 'string', required: false, description: 'Sales description' },
|
|
668
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Active status' },
|
|
669
|
+
],
|
|
670
|
+
},
|
|
671
|
+
// --------------------------------------------------------------------------
|
|
672
|
+
// ACCOUNTS (CHART OF ACCOUNTS)
|
|
673
|
+
// --------------------------------------------------------------------------
|
|
674
|
+
{
|
|
675
|
+
name: 'list_accounts',
|
|
676
|
+
description: 'List chart of accounts',
|
|
677
|
+
params: [
|
|
678
|
+
{ name: 'accountType', type: 'string', required: false, description: 'Filter by type: Bank, Expense, Income, etc.' },
|
|
679
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
680
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Filter by active status' },
|
|
681
|
+
],
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
name: 'get_account',
|
|
685
|
+
description: 'Get a specific account by ID',
|
|
686
|
+
params: [
|
|
687
|
+
{ name: 'accountId', type: 'string', required: true, description: 'The account ID' },
|
|
688
|
+
],
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
name: 'create_account',
|
|
692
|
+
description: 'Create a new account in chart of accounts',
|
|
693
|
+
params: [
|
|
694
|
+
{ name: 'name', type: 'string', required: true, description: 'Account name (must be unique)' },
|
|
695
|
+
{ name: 'accountType', type: 'string', required: true, description: 'Account type: Bank, Expense, Income, etc.' },
|
|
696
|
+
{ name: 'accountSubType', type: 'string', required: false, description: 'Account sub-type' },
|
|
697
|
+
{ name: 'description', type: 'string', required: false, description: 'Account description' },
|
|
698
|
+
],
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
name: 'update_account',
|
|
702
|
+
description: 'Update an existing account',
|
|
703
|
+
params: [
|
|
704
|
+
{ name: 'accountId', type: 'string', required: true, description: 'The account ID' },
|
|
705
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
706
|
+
{ name: 'name', type: 'string', required: false, description: 'Account name' },
|
|
707
|
+
{ name: 'description', type: 'string', required: false, description: 'Description' },
|
|
708
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Active status' },
|
|
709
|
+
],
|
|
710
|
+
},
|
|
711
|
+
// --------------------------------------------------------------------------
|
|
712
|
+
// EMPLOYEES
|
|
713
|
+
// --------------------------------------------------------------------------
|
|
714
|
+
{
|
|
715
|
+
name: 'list_employees',
|
|
716
|
+
description: 'List all employees',
|
|
717
|
+
params: [
|
|
718
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
719
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
720
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Filter by active status' },
|
|
721
|
+
],
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
name: 'get_employee',
|
|
725
|
+
description: 'Get a specific employee by ID',
|
|
726
|
+
params: [
|
|
727
|
+
{ name: 'employeeId', type: 'string', required: true, description: 'The employee ID' },
|
|
728
|
+
],
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
name: 'create_employee',
|
|
732
|
+
description: 'Create a new employee',
|
|
733
|
+
params: [
|
|
734
|
+
{ name: 'displayName', type: 'string', required: true, description: 'Display name' },
|
|
735
|
+
{ name: 'givenName', type: 'string', required: false, description: 'First name' },
|
|
736
|
+
{ name: 'familyName', type: 'string', required: false, description: 'Last name' },
|
|
737
|
+
{ name: 'email', type: 'string', required: false, description: 'Email address' },
|
|
738
|
+
{ name: 'phone', type: 'string', required: false, description: 'Phone number' },
|
|
739
|
+
],
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
name: 'update_employee',
|
|
743
|
+
description: 'Update an existing employee',
|
|
744
|
+
params: [
|
|
745
|
+
{ name: 'employeeId', type: 'string', required: true, description: 'The employee ID' },
|
|
746
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
747
|
+
{ name: 'displayName', type: 'string', required: false, description: 'Display name' },
|
|
748
|
+
{ name: 'email', type: 'string', required: false, description: 'Email' },
|
|
749
|
+
{ name: 'phone', type: 'string', required: false, description: 'Phone' },
|
|
750
|
+
{ name: 'active', type: 'boolean', required: false, description: 'Active status' },
|
|
751
|
+
],
|
|
752
|
+
},
|
|
753
|
+
// --------------------------------------------------------------------------
|
|
754
|
+
// JOURNAL ENTRIES
|
|
755
|
+
// --------------------------------------------------------------------------
|
|
756
|
+
{
|
|
757
|
+
name: 'list_journal_entries',
|
|
758
|
+
description: 'List all journal entries',
|
|
759
|
+
params: [
|
|
760
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
761
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
762
|
+
],
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
name: 'get_journal_entry',
|
|
766
|
+
description: 'Get a specific journal entry',
|
|
767
|
+
params: [
|
|
768
|
+
{ name: 'journalEntryId', type: 'string', required: true, description: 'The journal entry ID' },
|
|
769
|
+
],
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
name: 'create_journal_entry',
|
|
773
|
+
description: 'Create a journal entry',
|
|
774
|
+
params: [
|
|
775
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of debit/credit lines [{accountId, amount, postingType: Debit|Credit, description}]' },
|
|
776
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
777
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
778
|
+
],
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
name: 'delete_journal_entry',
|
|
782
|
+
description: 'Delete a journal entry',
|
|
783
|
+
params: [
|
|
784
|
+
{ name: 'journalEntryId', type: 'string', required: true, description: 'The journal entry ID' },
|
|
785
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
786
|
+
],
|
|
787
|
+
},
|
|
788
|
+
// --------------------------------------------------------------------------
|
|
789
|
+
// DEPOSITS
|
|
790
|
+
// --------------------------------------------------------------------------
|
|
791
|
+
{
|
|
792
|
+
name: 'list_deposits',
|
|
793
|
+
description: 'List all deposits',
|
|
794
|
+
params: [
|
|
795
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
796
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
797
|
+
],
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: 'get_deposit',
|
|
801
|
+
description: 'Get a specific deposit',
|
|
802
|
+
params: [
|
|
803
|
+
{ name: 'depositId', type: 'string', required: true, description: 'The deposit ID' },
|
|
804
|
+
],
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
name: 'create_deposit',
|
|
808
|
+
description: 'Create a deposit',
|
|
809
|
+
params: [
|
|
810
|
+
{ name: 'depositToAccountId', type: 'string', required: true, description: 'Bank account ID to deposit to' },
|
|
811
|
+
{ name: 'lineItems', type: 'array', required: true, description: 'Array of deposit lines [{accountId, amount, description}]' },
|
|
812
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
813
|
+
],
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
name: 'delete_deposit',
|
|
817
|
+
description: 'Delete a deposit',
|
|
818
|
+
params: [
|
|
819
|
+
{ name: 'depositId', type: 'string', required: true, description: 'The deposit ID' },
|
|
820
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
821
|
+
],
|
|
822
|
+
},
|
|
823
|
+
// --------------------------------------------------------------------------
|
|
824
|
+
// TRANSFERS
|
|
825
|
+
// --------------------------------------------------------------------------
|
|
826
|
+
{
|
|
827
|
+
name: 'list_transfers',
|
|
828
|
+
description: 'List all transfers between accounts',
|
|
829
|
+
params: [
|
|
830
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
831
|
+
{ name: 'offset', type: 'number', required: false, description: 'Starting position' },
|
|
832
|
+
],
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
name: 'get_transfer',
|
|
836
|
+
description: 'Get a specific transfer',
|
|
837
|
+
params: [
|
|
838
|
+
{ name: 'transferId', type: 'string', required: true, description: 'The transfer ID' },
|
|
839
|
+
],
|
|
840
|
+
},
|
|
841
|
+
{
|
|
842
|
+
name: 'create_transfer',
|
|
843
|
+
description: 'Create a transfer between accounts',
|
|
844
|
+
params: [
|
|
845
|
+
{ name: 'fromAccountId', type: 'string', required: true, description: 'Source account ID' },
|
|
846
|
+
{ name: 'toAccountId', type: 'string', required: true, description: 'Destination account ID' },
|
|
847
|
+
{ name: 'amount', type: 'number', required: true, description: 'Transfer amount' },
|
|
848
|
+
{ name: 'txnDate', type: 'string', required: false, description: 'Transaction date' },
|
|
849
|
+
{ name: 'privateNote', type: 'string', required: false, description: 'Private note' },
|
|
850
|
+
],
|
|
851
|
+
},
|
|
852
|
+
{
|
|
853
|
+
name: 'delete_transfer',
|
|
854
|
+
description: 'Delete a transfer',
|
|
855
|
+
params: [
|
|
856
|
+
{ name: 'transferId', type: 'string', required: true, description: 'The transfer ID' },
|
|
857
|
+
{ name: 'syncToken', type: 'string', required: true, description: 'Current sync token' },
|
|
858
|
+
],
|
|
859
|
+
},
|
|
860
|
+
// --------------------------------------------------------------------------
|
|
861
|
+
// TAX
|
|
862
|
+
// --------------------------------------------------------------------------
|
|
863
|
+
{
|
|
864
|
+
name: 'list_tax_codes',
|
|
865
|
+
description: 'List all tax codes',
|
|
866
|
+
params: [
|
|
867
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
868
|
+
],
|
|
869
|
+
},
|
|
870
|
+
{
|
|
871
|
+
name: 'list_tax_rates',
|
|
872
|
+
description: 'List all tax rates',
|
|
873
|
+
params: [
|
|
874
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
875
|
+
],
|
|
876
|
+
},
|
|
877
|
+
// --------------------------------------------------------------------------
|
|
878
|
+
// PAYMENT METHODS
|
|
879
|
+
// --------------------------------------------------------------------------
|
|
880
|
+
{
|
|
881
|
+
name: 'list_payment_methods',
|
|
882
|
+
description: 'List all payment methods',
|
|
883
|
+
params: [
|
|
884
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
885
|
+
],
|
|
886
|
+
},
|
|
887
|
+
// --------------------------------------------------------------------------
|
|
888
|
+
// TERMS
|
|
889
|
+
// --------------------------------------------------------------------------
|
|
890
|
+
{
|
|
891
|
+
name: 'list_terms',
|
|
892
|
+
description: 'List all payment terms (Net 30, Due on Receipt, etc.)',
|
|
893
|
+
params: [
|
|
894
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
895
|
+
],
|
|
896
|
+
},
|
|
897
|
+
// --------------------------------------------------------------------------
|
|
898
|
+
// CLASSES / DEPARTMENTS
|
|
899
|
+
// --------------------------------------------------------------------------
|
|
900
|
+
{
|
|
901
|
+
name: 'list_classes',
|
|
902
|
+
description: 'List all classes (for tracking)',
|
|
903
|
+
params: [
|
|
904
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
905
|
+
],
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
name: 'list_departments',
|
|
909
|
+
description: 'List all departments/locations',
|
|
910
|
+
params: [
|
|
911
|
+
{ name: 'limit', type: 'number', required: false, description: 'Maximum number of results' },
|
|
912
|
+
],
|
|
913
|
+
},
|
|
914
|
+
// --------------------------------------------------------------------------
|
|
915
|
+
// REPORTS
|
|
916
|
+
// --------------------------------------------------------------------------
|
|
917
|
+
{
|
|
918
|
+
name: 'get_profit_loss_report',
|
|
919
|
+
description: 'Get Profit and Loss (Income Statement) report',
|
|
920
|
+
params: [
|
|
921
|
+
{ name: 'startDate', type: 'string', required: false, description: 'Start date (YYYY-MM-DD)' },
|
|
922
|
+
{ name: 'endDate', type: 'string', required: false, description: 'End date (YYYY-MM-DD)' },
|
|
923
|
+
{ name: 'summarizeBy', type: 'string', required: false, description: 'Summarize by: Total, Month, Week, Days' },
|
|
924
|
+
],
|
|
925
|
+
},
|
|
926
|
+
{
|
|
927
|
+
name: 'get_balance_sheet_report',
|
|
928
|
+
description: 'Get Balance Sheet report',
|
|
929
|
+
params: [
|
|
930
|
+
{ name: 'startDate', type: 'string', required: false, description: 'Start date' },
|
|
931
|
+
{ name: 'endDate', type: 'string', required: false, description: 'End date' },
|
|
932
|
+
{ name: 'summarizeBy', type: 'string', required: false, description: 'Summarize by: Total, Month, Week, Days' },
|
|
933
|
+
],
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
name: 'get_cash_flow_report',
|
|
937
|
+
description: 'Get Statement of Cash Flows report',
|
|
938
|
+
params: [
|
|
939
|
+
{ name: 'startDate', type: 'string', required: false, description: 'Start date' },
|
|
940
|
+
{ name: 'endDate', type: 'string', required: false, description: 'End date' },
|
|
941
|
+
{ name: 'summarizeBy', type: 'string', required: false, description: 'Summarize by: Total, Month, Week, Days' },
|
|
942
|
+
],
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
name: 'get_ar_aging_report',
|
|
946
|
+
description: 'Get Accounts Receivable Aging report',
|
|
947
|
+
params: [
|
|
948
|
+
{ name: 'reportDate', type: 'string', required: false, description: 'Report date (YYYY-MM-DD)' },
|
|
949
|
+
{ name: 'agingMethod', type: 'string', required: false, description: 'Aging method: Report_Date or Current' },
|
|
950
|
+
],
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
name: 'get_ap_aging_report',
|
|
954
|
+
description: 'Get Accounts Payable Aging report',
|
|
955
|
+
params: [
|
|
956
|
+
{ name: 'reportDate', type: 'string', required: false, description: 'Report date (YYYY-MM-DD)' },
|
|
957
|
+
{ name: 'agingMethod', type: 'string', required: false, description: 'Aging method: Report_Date or Current' },
|
|
958
|
+
],
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
name: 'get_customer_balance_report',
|
|
962
|
+
description: 'Get Customer Balance Summary report',
|
|
963
|
+
params: [
|
|
964
|
+
{ name: 'reportDate', type: 'string', required: false, description: 'Report date' },
|
|
965
|
+
],
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
name: 'get_vendor_balance_report',
|
|
969
|
+
description: 'Get Vendor Balance Summary report',
|
|
970
|
+
params: [
|
|
971
|
+
{ name: 'reportDate', type: 'string', required: false, description: 'Report date' },
|
|
972
|
+
],
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
name: 'get_general_ledger_report',
|
|
976
|
+
description: 'Get General Ledger report',
|
|
977
|
+
params: [
|
|
978
|
+
{ name: 'startDate', type: 'string', required: false, description: 'Start date' },
|
|
979
|
+
{ name: 'endDate', type: 'string', required: false, description: 'End date' },
|
|
980
|
+
],
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
name: 'get_trial_balance_report',
|
|
984
|
+
description: 'Get Trial Balance report',
|
|
985
|
+
params: [
|
|
986
|
+
{ name: 'startDate', type: 'string', required: false, description: 'Start date' },
|
|
987
|
+
{ name: 'endDate', type: 'string', required: false, description: 'End date' },
|
|
988
|
+
],
|
|
989
|
+
},
|
|
990
|
+
// --------------------------------------------------------------------------
|
|
991
|
+
// RAW QUERY
|
|
992
|
+
// --------------------------------------------------------------------------
|
|
993
|
+
{
|
|
994
|
+
name: 'query',
|
|
995
|
+
description: 'Run a SQL-like query against QuickBooks data. Example: "SELECT * FROM Customer WHERE DisplayName LIKE \'%Smith%\'"',
|
|
996
|
+
params: [
|
|
997
|
+
{ name: 'query', type: 'string', required: true, description: 'SQL-like query string' },
|
|
998
|
+
],
|
|
999
|
+
},
|
|
1000
|
+
];
|
|
1001
|
+
// ============================================================================
|
|
1002
|
+
// ACTION IMPLEMENTATIONS
|
|
1003
|
+
// ============================================================================
|
|
1004
|
+
// --------------------------------------------------------------------------
|
|
1005
|
+
// COMPANY
|
|
1006
|
+
// --------------------------------------------------------------------------
|
|
1007
|
+
async function getCompanyInfo() {
|
|
1008
|
+
return qbRequest('companyinfo/' + REALM_ID);
|
|
1009
|
+
}
|
|
1010
|
+
async function getPreferences() {
|
|
1011
|
+
return qbRequest('preferences');
|
|
1012
|
+
}
|
|
1013
|
+
// --------------------------------------------------------------------------
|
|
1014
|
+
// CUSTOMERS
|
|
1015
|
+
// --------------------------------------------------------------------------
|
|
1016
|
+
async function listCustomers(params) {
|
|
1017
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1018
|
+
const offset = Number(params.offset) || 1;
|
|
1019
|
+
const active = params.active;
|
|
1020
|
+
let query = `SELECT * FROM Customer`;
|
|
1021
|
+
if (active !== undefined) {
|
|
1022
|
+
query += ` WHERE Active = ${active}`;
|
|
1023
|
+
}
|
|
1024
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1025
|
+
return qbQuery(query);
|
|
1026
|
+
}
|
|
1027
|
+
async function getCustomer(params) {
|
|
1028
|
+
const { customerId } = params;
|
|
1029
|
+
if (!customerId)
|
|
1030
|
+
throw new Error('customerId is required');
|
|
1031
|
+
return qbRequest(`customer/${customerId}`);
|
|
1032
|
+
}
|
|
1033
|
+
async function createCustomer(params) {
|
|
1034
|
+
const { displayName, companyName, givenName, familyName, email, phone, billingAddress } = params;
|
|
1035
|
+
if (!displayName)
|
|
1036
|
+
throw new Error('displayName is required');
|
|
1037
|
+
const customer = { DisplayName: displayName };
|
|
1038
|
+
if (companyName)
|
|
1039
|
+
customer.CompanyName = companyName;
|
|
1040
|
+
if (givenName)
|
|
1041
|
+
customer.GivenName = givenName;
|
|
1042
|
+
if (familyName)
|
|
1043
|
+
customer.FamilyName = familyName;
|
|
1044
|
+
if (email)
|
|
1045
|
+
customer.PrimaryEmailAddr = { Address: email };
|
|
1046
|
+
if (phone)
|
|
1047
|
+
customer.PrimaryPhone = { FreeFormNumber: phone };
|
|
1048
|
+
if (billingAddress)
|
|
1049
|
+
customer.BillAddr = billingAddress;
|
|
1050
|
+
return qbRequest('customer', 'POST', customer);
|
|
1051
|
+
}
|
|
1052
|
+
async function updateCustomer(params) {
|
|
1053
|
+
const { customerId, syncToken, displayName, companyName, givenName, familyName, email, phone, active } = params;
|
|
1054
|
+
if (!customerId || !syncToken)
|
|
1055
|
+
throw new Error('customerId and syncToken are required');
|
|
1056
|
+
const customer = { Id: customerId, SyncToken: syncToken, sparse: true };
|
|
1057
|
+
if (displayName)
|
|
1058
|
+
customer.DisplayName = displayName;
|
|
1059
|
+
if (companyName)
|
|
1060
|
+
customer.CompanyName = companyName;
|
|
1061
|
+
if (givenName)
|
|
1062
|
+
customer.GivenName = givenName;
|
|
1063
|
+
if (familyName)
|
|
1064
|
+
customer.FamilyName = familyName;
|
|
1065
|
+
if (email)
|
|
1066
|
+
customer.PrimaryEmailAddr = { Address: email };
|
|
1067
|
+
if (phone)
|
|
1068
|
+
customer.PrimaryPhone = { FreeFormNumber: phone };
|
|
1069
|
+
if (active !== undefined)
|
|
1070
|
+
customer.Active = active;
|
|
1071
|
+
return qbRequest('customer', 'POST', customer);
|
|
1072
|
+
}
|
|
1073
|
+
// --------------------------------------------------------------------------
|
|
1074
|
+
// INVOICES
|
|
1075
|
+
// --------------------------------------------------------------------------
|
|
1076
|
+
async function listInvoices(params) {
|
|
1077
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1078
|
+
const offset = Number(params.offset) || 1;
|
|
1079
|
+
const status = params.status;
|
|
1080
|
+
const customerId = params.customerId;
|
|
1081
|
+
let query = `SELECT * FROM Invoice`;
|
|
1082
|
+
const conditions = [];
|
|
1083
|
+
if (status) {
|
|
1084
|
+
if (status.toLowerCase() === 'paid')
|
|
1085
|
+
conditions.push(`Balance = '0'`);
|
|
1086
|
+
else if (status.toLowerCase() === 'unpaid')
|
|
1087
|
+
conditions.push(`Balance > '0'`);
|
|
1088
|
+
}
|
|
1089
|
+
if (customerId)
|
|
1090
|
+
conditions.push(`CustomerRef = '${customerId}'`);
|
|
1091
|
+
if (conditions.length > 0)
|
|
1092
|
+
query += ` WHERE ${conditions.join(' AND ')}`;
|
|
1093
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1094
|
+
return qbQuery(query);
|
|
1095
|
+
}
|
|
1096
|
+
async function getInvoice(params) {
|
|
1097
|
+
const { invoiceId } = params;
|
|
1098
|
+
if (!invoiceId)
|
|
1099
|
+
throw new Error('invoiceId is required');
|
|
1100
|
+
return qbRequest(`invoice/${invoiceId}`);
|
|
1101
|
+
}
|
|
1102
|
+
async function createInvoice(params) {
|
|
1103
|
+
const { customerId, lineItems, dueDate, txnDate, privateNote, customerMemo } = params;
|
|
1104
|
+
if (!customerId || !lineItems)
|
|
1105
|
+
throw new Error('customerId and lineItems are required');
|
|
1106
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1107
|
+
Id: String(idx + 1),
|
|
1108
|
+
LineNum: idx + 1,
|
|
1109
|
+
Amount: item.amount,
|
|
1110
|
+
Description: item.description,
|
|
1111
|
+
DetailType: 'SalesItemLineDetail',
|
|
1112
|
+
SalesItemLineDetail: {
|
|
1113
|
+
ItemRef: { value: item.itemId },
|
|
1114
|
+
Qty: item.quantity || 1,
|
|
1115
|
+
},
|
|
1116
|
+
}));
|
|
1117
|
+
const invoice = {
|
|
1118
|
+
CustomerRef: { value: customerId },
|
|
1119
|
+
Line: lines,
|
|
1120
|
+
};
|
|
1121
|
+
if (dueDate)
|
|
1122
|
+
invoice.DueDate = dueDate;
|
|
1123
|
+
if (txnDate)
|
|
1124
|
+
invoice.TxnDate = txnDate;
|
|
1125
|
+
if (privateNote)
|
|
1126
|
+
invoice.PrivateNote = privateNote;
|
|
1127
|
+
if (customerMemo)
|
|
1128
|
+
invoice.CustomerMemo = { value: customerMemo };
|
|
1129
|
+
return qbRequest('invoice', 'POST', invoice);
|
|
1130
|
+
}
|
|
1131
|
+
async function updateInvoice(params) {
|
|
1132
|
+
const { invoiceId, syncToken, lineItems, dueDate, privateNote, customerMemo } = params;
|
|
1133
|
+
if (!invoiceId || !syncToken)
|
|
1134
|
+
throw new Error('invoiceId and syncToken are required');
|
|
1135
|
+
const invoice = { Id: invoiceId, SyncToken: syncToken, sparse: true };
|
|
1136
|
+
if (lineItems) {
|
|
1137
|
+
invoice.Line = lineItems.map((item, idx) => ({
|
|
1138
|
+
Id: String(idx + 1),
|
|
1139
|
+
LineNum: idx + 1,
|
|
1140
|
+
Amount: item.amount,
|
|
1141
|
+
Description: item.description,
|
|
1142
|
+
DetailType: 'SalesItemLineDetail',
|
|
1143
|
+
SalesItemLineDetail: {
|
|
1144
|
+
ItemRef: { value: item.itemId },
|
|
1145
|
+
Qty: item.quantity || 1,
|
|
1146
|
+
},
|
|
1147
|
+
}));
|
|
1148
|
+
}
|
|
1149
|
+
if (dueDate)
|
|
1150
|
+
invoice.DueDate = dueDate;
|
|
1151
|
+
if (privateNote)
|
|
1152
|
+
invoice.PrivateNote = privateNote;
|
|
1153
|
+
if (customerMemo)
|
|
1154
|
+
invoice.CustomerMemo = { value: customerMemo };
|
|
1155
|
+
return qbRequest('invoice', 'POST', invoice);
|
|
1156
|
+
}
|
|
1157
|
+
async function deleteInvoice(params) {
|
|
1158
|
+
const { invoiceId, syncToken } = params;
|
|
1159
|
+
if (!invoiceId || !syncToken)
|
|
1160
|
+
throw new Error('invoiceId and syncToken are required');
|
|
1161
|
+
return qbRequest(`invoice?operation=delete`, 'POST', { Id: invoiceId, SyncToken: syncToken });
|
|
1162
|
+
}
|
|
1163
|
+
async function sendInvoice(params) {
|
|
1164
|
+
const { invoiceId, email } = params;
|
|
1165
|
+
if (!invoiceId)
|
|
1166
|
+
throw new Error('invoiceId is required');
|
|
1167
|
+
const endpoint = email ? `invoice/${invoiceId}/send?sendTo=${encodeURIComponent(String(email))}` : `invoice/${invoiceId}/send`;
|
|
1168
|
+
return qbRequest(endpoint, 'POST');
|
|
1169
|
+
}
|
|
1170
|
+
async function voidInvoice(params) {
|
|
1171
|
+
const { invoiceId, syncToken } = params;
|
|
1172
|
+
if (!invoiceId || !syncToken)
|
|
1173
|
+
throw new Error('invoiceId and syncToken are required');
|
|
1174
|
+
return qbRequest(`invoice?operation=void`, 'POST', { Id: invoiceId, SyncToken: syncToken });
|
|
1175
|
+
}
|
|
1176
|
+
// --------------------------------------------------------------------------
|
|
1177
|
+
// ESTIMATES
|
|
1178
|
+
// --------------------------------------------------------------------------
|
|
1179
|
+
async function listEstimates(params) {
|
|
1180
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1181
|
+
const offset = Number(params.offset) || 1;
|
|
1182
|
+
const customerId = params.customerId;
|
|
1183
|
+
let query = `SELECT * FROM Estimate`;
|
|
1184
|
+
if (customerId)
|
|
1185
|
+
query += ` WHERE CustomerRef = '${customerId}'`;
|
|
1186
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1187
|
+
return qbQuery(query);
|
|
1188
|
+
}
|
|
1189
|
+
async function getEstimate(params) {
|
|
1190
|
+
const { estimateId } = params;
|
|
1191
|
+
if (!estimateId)
|
|
1192
|
+
throw new Error('estimateId is required');
|
|
1193
|
+
return qbRequest(`estimate/${estimateId}`);
|
|
1194
|
+
}
|
|
1195
|
+
async function createEstimate(params) {
|
|
1196
|
+
const { customerId, lineItems, expirationDate, txnDate, privateNote, customerMemo } = params;
|
|
1197
|
+
if (!customerId || !lineItems)
|
|
1198
|
+
throw new Error('customerId and lineItems are required');
|
|
1199
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1200
|
+
Id: String(idx + 1),
|
|
1201
|
+
LineNum: idx + 1,
|
|
1202
|
+
Amount: item.amount,
|
|
1203
|
+
Description: item.description,
|
|
1204
|
+
DetailType: 'SalesItemLineDetail',
|
|
1205
|
+
SalesItemLineDetail: {
|
|
1206
|
+
ItemRef: { value: item.itemId },
|
|
1207
|
+
Qty: item.quantity || 1,
|
|
1208
|
+
},
|
|
1209
|
+
}));
|
|
1210
|
+
const estimate = {
|
|
1211
|
+
CustomerRef: { value: customerId },
|
|
1212
|
+
Line: lines,
|
|
1213
|
+
};
|
|
1214
|
+
if (expirationDate)
|
|
1215
|
+
estimate.ExpirationDate = expirationDate;
|
|
1216
|
+
if (txnDate)
|
|
1217
|
+
estimate.TxnDate = txnDate;
|
|
1218
|
+
if (privateNote)
|
|
1219
|
+
estimate.PrivateNote = privateNote;
|
|
1220
|
+
if (customerMemo)
|
|
1221
|
+
estimate.CustomerMemo = { value: customerMemo };
|
|
1222
|
+
return qbRequest('estimate', 'POST', estimate);
|
|
1223
|
+
}
|
|
1224
|
+
async function updateEstimate(params) {
|
|
1225
|
+
const { estimateId, syncToken, lineItems, expirationDate, txnStatus } = params;
|
|
1226
|
+
if (!estimateId || !syncToken)
|
|
1227
|
+
throw new Error('estimateId and syncToken are required');
|
|
1228
|
+
const estimate = { Id: estimateId, SyncToken: syncToken, sparse: true };
|
|
1229
|
+
if (lineItems) {
|
|
1230
|
+
estimate.Line = lineItems.map((item, idx) => ({
|
|
1231
|
+
Id: String(idx + 1),
|
|
1232
|
+
Amount: item.amount,
|
|
1233
|
+
DetailType: 'SalesItemLineDetail',
|
|
1234
|
+
SalesItemLineDetail: { ItemRef: { value: item.itemId }, Qty: item.quantity || 1 },
|
|
1235
|
+
}));
|
|
1236
|
+
}
|
|
1237
|
+
if (expirationDate)
|
|
1238
|
+
estimate.ExpirationDate = expirationDate;
|
|
1239
|
+
if (txnStatus)
|
|
1240
|
+
estimate.TxnStatus = txnStatus;
|
|
1241
|
+
return qbRequest('estimate', 'POST', estimate);
|
|
1242
|
+
}
|
|
1243
|
+
async function deleteEstimate(params) {
|
|
1244
|
+
const { estimateId, syncToken } = params;
|
|
1245
|
+
if (!estimateId || !syncToken)
|
|
1246
|
+
throw new Error('estimateId and syncToken are required');
|
|
1247
|
+
return qbRequest(`estimate?operation=delete`, 'POST', { Id: estimateId, SyncToken: syncToken });
|
|
1248
|
+
}
|
|
1249
|
+
async function sendEstimate(params) {
|
|
1250
|
+
const { estimateId, email } = params;
|
|
1251
|
+
if (!estimateId)
|
|
1252
|
+
throw new Error('estimateId is required');
|
|
1253
|
+
const endpoint = email ? `estimate/${estimateId}/send?sendTo=${encodeURIComponent(String(email))}` : `estimate/${estimateId}/send`;
|
|
1254
|
+
return qbRequest(endpoint, 'POST');
|
|
1255
|
+
}
|
|
1256
|
+
// --------------------------------------------------------------------------
|
|
1257
|
+
// PAYMENTS
|
|
1258
|
+
// --------------------------------------------------------------------------
|
|
1259
|
+
async function listPayments(params) {
|
|
1260
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1261
|
+
const offset = Number(params.offset) || 1;
|
|
1262
|
+
const customerId = params.customerId;
|
|
1263
|
+
let query = `SELECT * FROM Payment`;
|
|
1264
|
+
if (customerId)
|
|
1265
|
+
query += ` WHERE CustomerRef = '${customerId}'`;
|
|
1266
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1267
|
+
return qbQuery(query);
|
|
1268
|
+
}
|
|
1269
|
+
async function getPayment(params) {
|
|
1270
|
+
const { paymentId } = params;
|
|
1271
|
+
if (!paymentId)
|
|
1272
|
+
throw new Error('paymentId is required');
|
|
1273
|
+
return qbRequest(`payment/${paymentId}`);
|
|
1274
|
+
}
|
|
1275
|
+
async function createPayment(params) {
|
|
1276
|
+
const { customerId, totalAmt, txnDate, paymentMethodId, depositToAccountId, invoiceIds, privateNote } = params;
|
|
1277
|
+
if (!customerId || totalAmt === undefined)
|
|
1278
|
+
throw new Error('customerId and totalAmt are required');
|
|
1279
|
+
const payment = {
|
|
1280
|
+
CustomerRef: { value: customerId },
|
|
1281
|
+
TotalAmt: totalAmt,
|
|
1282
|
+
};
|
|
1283
|
+
if (txnDate)
|
|
1284
|
+
payment.TxnDate = txnDate;
|
|
1285
|
+
if (paymentMethodId)
|
|
1286
|
+
payment.PaymentMethodRef = { value: paymentMethodId };
|
|
1287
|
+
if (depositToAccountId)
|
|
1288
|
+
payment.DepositToAccountRef = { value: depositToAccountId };
|
|
1289
|
+
if (privateNote)
|
|
1290
|
+
payment.PrivateNote = privateNote;
|
|
1291
|
+
if (invoiceIds && Array.isArray(invoiceIds)) {
|
|
1292
|
+
payment.Line = invoiceIds.map(id => ({
|
|
1293
|
+
Amount: totalAmt / invoiceIds.length,
|
|
1294
|
+
LinkedTxn: [{ TxnId: id, TxnType: 'Invoice' }],
|
|
1295
|
+
}));
|
|
1296
|
+
}
|
|
1297
|
+
return qbRequest('payment', 'POST', payment);
|
|
1298
|
+
}
|
|
1299
|
+
async function updatePayment(params) {
|
|
1300
|
+
const { paymentId, syncToken, totalAmt, txnDate } = params;
|
|
1301
|
+
if (!paymentId || !syncToken)
|
|
1302
|
+
throw new Error('paymentId and syncToken are required');
|
|
1303
|
+
const payment = { Id: paymentId, SyncToken: syncToken, sparse: true };
|
|
1304
|
+
if (totalAmt !== undefined)
|
|
1305
|
+
payment.TotalAmt = totalAmt;
|
|
1306
|
+
if (txnDate)
|
|
1307
|
+
payment.TxnDate = txnDate;
|
|
1308
|
+
return qbRequest('payment', 'POST', payment);
|
|
1309
|
+
}
|
|
1310
|
+
async function deletePayment(params) {
|
|
1311
|
+
const { paymentId, syncToken } = params;
|
|
1312
|
+
if (!paymentId || !syncToken)
|
|
1313
|
+
throw new Error('paymentId and syncToken are required');
|
|
1314
|
+
return qbRequest(`payment?operation=delete`, 'POST', { Id: paymentId, SyncToken: syncToken });
|
|
1315
|
+
}
|
|
1316
|
+
async function voidPayment(params) {
|
|
1317
|
+
const { paymentId, syncToken } = params;
|
|
1318
|
+
if (!paymentId || !syncToken)
|
|
1319
|
+
throw new Error('paymentId and syncToken are required');
|
|
1320
|
+
return qbRequest(`payment?operation=void`, 'POST', { Id: paymentId, SyncToken: syncToken });
|
|
1321
|
+
}
|
|
1322
|
+
// --------------------------------------------------------------------------
|
|
1323
|
+
// SALES RECEIPTS
|
|
1324
|
+
// --------------------------------------------------------------------------
|
|
1325
|
+
async function listSalesReceipts(params) {
|
|
1326
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1327
|
+
const offset = Number(params.offset) || 1;
|
|
1328
|
+
return qbQuery(`SELECT * FROM SalesReceipt MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1329
|
+
}
|
|
1330
|
+
async function getSalesReceipt(params) {
|
|
1331
|
+
const { salesReceiptId } = params;
|
|
1332
|
+
if (!salesReceiptId)
|
|
1333
|
+
throw new Error('salesReceiptId is required');
|
|
1334
|
+
return qbRequest(`salesreceipt/${salesReceiptId}`);
|
|
1335
|
+
}
|
|
1336
|
+
async function createSalesReceipt(params) {
|
|
1337
|
+
const { customerId, lineItems, txnDate, paymentMethodId, depositToAccountId } = params;
|
|
1338
|
+
if (!lineItems)
|
|
1339
|
+
throw new Error('lineItems is required');
|
|
1340
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1341
|
+
Id: String(idx + 1),
|
|
1342
|
+
Amount: item.amount,
|
|
1343
|
+
DetailType: 'SalesItemLineDetail',
|
|
1344
|
+
SalesItemLineDetail: { ItemRef: { value: item.itemId }, Qty: item.quantity || 1 },
|
|
1345
|
+
}));
|
|
1346
|
+
const receipt = { Line: lines };
|
|
1347
|
+
if (customerId)
|
|
1348
|
+
receipt.CustomerRef = { value: customerId };
|
|
1349
|
+
if (txnDate)
|
|
1350
|
+
receipt.TxnDate = txnDate;
|
|
1351
|
+
if (paymentMethodId)
|
|
1352
|
+
receipt.PaymentMethodRef = { value: paymentMethodId };
|
|
1353
|
+
if (depositToAccountId)
|
|
1354
|
+
receipt.DepositToAccountRef = { value: depositToAccountId };
|
|
1355
|
+
return qbRequest('salesreceipt', 'POST', receipt);
|
|
1356
|
+
}
|
|
1357
|
+
async function deleteSalesReceipt(params) {
|
|
1358
|
+
const { salesReceiptId, syncToken } = params;
|
|
1359
|
+
if (!salesReceiptId || !syncToken)
|
|
1360
|
+
throw new Error('salesReceiptId and syncToken are required');
|
|
1361
|
+
return qbRequest(`salesreceipt?operation=delete`, 'POST', { Id: salesReceiptId, SyncToken: syncToken });
|
|
1362
|
+
}
|
|
1363
|
+
// --------------------------------------------------------------------------
|
|
1364
|
+
// CREDIT MEMOS
|
|
1365
|
+
// --------------------------------------------------------------------------
|
|
1366
|
+
async function listCreditMemos(params) {
|
|
1367
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1368
|
+
const offset = Number(params.offset) || 1;
|
|
1369
|
+
return qbQuery(`SELECT * FROM CreditMemo MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1370
|
+
}
|
|
1371
|
+
async function getCreditMemo(params) {
|
|
1372
|
+
const { creditMemoId } = params;
|
|
1373
|
+
if (!creditMemoId)
|
|
1374
|
+
throw new Error('creditMemoId is required');
|
|
1375
|
+
return qbRequest(`creditmemo/${creditMemoId}`);
|
|
1376
|
+
}
|
|
1377
|
+
async function createCreditMemo(params) {
|
|
1378
|
+
const { customerId, lineItems, txnDate, privateNote } = params;
|
|
1379
|
+
if (!customerId || !lineItems)
|
|
1380
|
+
throw new Error('customerId and lineItems are required');
|
|
1381
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1382
|
+
Id: String(idx + 1),
|
|
1383
|
+
Amount: item.amount,
|
|
1384
|
+
DetailType: 'SalesItemLineDetail',
|
|
1385
|
+
SalesItemLineDetail: { ItemRef: { value: item.itemId }, Qty: item.quantity || 1 },
|
|
1386
|
+
}));
|
|
1387
|
+
const memo = { CustomerRef: { value: customerId }, Line: lines };
|
|
1388
|
+
if (txnDate)
|
|
1389
|
+
memo.TxnDate = txnDate;
|
|
1390
|
+
if (privateNote)
|
|
1391
|
+
memo.PrivateNote = privateNote;
|
|
1392
|
+
return qbRequest('creditmemo', 'POST', memo);
|
|
1393
|
+
}
|
|
1394
|
+
async function deleteCreditMemo(params) {
|
|
1395
|
+
const { creditMemoId, syncToken } = params;
|
|
1396
|
+
if (!creditMemoId || !syncToken)
|
|
1397
|
+
throw new Error('creditMemoId and syncToken are required');
|
|
1398
|
+
return qbRequest(`creditmemo?operation=delete`, 'POST', { Id: creditMemoId, SyncToken: syncToken });
|
|
1399
|
+
}
|
|
1400
|
+
// --------------------------------------------------------------------------
|
|
1401
|
+
// REFUND RECEIPTS
|
|
1402
|
+
// --------------------------------------------------------------------------
|
|
1403
|
+
async function listRefundReceipts(params) {
|
|
1404
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1405
|
+
const offset = Number(params.offset) || 1;
|
|
1406
|
+
return qbQuery(`SELECT * FROM RefundReceipt MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1407
|
+
}
|
|
1408
|
+
async function getRefundReceipt(params) {
|
|
1409
|
+
const { refundReceiptId } = params;
|
|
1410
|
+
if (!refundReceiptId)
|
|
1411
|
+
throw new Error('refundReceiptId is required');
|
|
1412
|
+
return qbRequest(`refundreceipt/${refundReceiptId}`);
|
|
1413
|
+
}
|
|
1414
|
+
async function createRefundReceipt(params) {
|
|
1415
|
+
const { customerId, lineItems, txnDate, depositToAccountId } = params;
|
|
1416
|
+
if (!customerId || !lineItems)
|
|
1417
|
+
throw new Error('customerId and lineItems are required');
|
|
1418
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1419
|
+
Id: String(idx + 1),
|
|
1420
|
+
Amount: item.amount,
|
|
1421
|
+
DetailType: 'SalesItemLineDetail',
|
|
1422
|
+
SalesItemLineDetail: { ItemRef: { value: item.itemId }, Qty: item.quantity || 1 },
|
|
1423
|
+
}));
|
|
1424
|
+
const refund = { CustomerRef: { value: customerId }, Line: lines };
|
|
1425
|
+
if (txnDate)
|
|
1426
|
+
refund.TxnDate = txnDate;
|
|
1427
|
+
if (depositToAccountId)
|
|
1428
|
+
refund.DepositToAccountRef = { value: depositToAccountId };
|
|
1429
|
+
return qbRequest('refundreceipt', 'POST', refund);
|
|
1430
|
+
}
|
|
1431
|
+
async function deleteRefundReceipt(params) {
|
|
1432
|
+
const { refundReceiptId, syncToken } = params;
|
|
1433
|
+
if (!refundReceiptId || !syncToken)
|
|
1434
|
+
throw new Error('refundReceiptId and syncToken are required');
|
|
1435
|
+
return qbRequest(`refundreceipt?operation=delete`, 'POST', { Id: refundReceiptId, SyncToken: syncToken });
|
|
1436
|
+
}
|
|
1437
|
+
// --------------------------------------------------------------------------
|
|
1438
|
+
// VENDORS
|
|
1439
|
+
// --------------------------------------------------------------------------
|
|
1440
|
+
async function listVendors(params) {
|
|
1441
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1442
|
+
const offset = Number(params.offset) || 1;
|
|
1443
|
+
const active = params.active;
|
|
1444
|
+
let query = `SELECT * FROM Vendor`;
|
|
1445
|
+
if (active !== undefined)
|
|
1446
|
+
query += ` WHERE Active = ${active}`;
|
|
1447
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1448
|
+
return qbQuery(query);
|
|
1449
|
+
}
|
|
1450
|
+
async function getVendor(params) {
|
|
1451
|
+
const { vendorId } = params;
|
|
1452
|
+
if (!vendorId)
|
|
1453
|
+
throw new Error('vendorId is required');
|
|
1454
|
+
return qbRequest(`vendor/${vendorId}`);
|
|
1455
|
+
}
|
|
1456
|
+
async function createVendor(params) {
|
|
1457
|
+
const { displayName, companyName, givenName, familyName, email, phone } = params;
|
|
1458
|
+
if (!displayName)
|
|
1459
|
+
throw new Error('displayName is required');
|
|
1460
|
+
const vendor = { DisplayName: displayName };
|
|
1461
|
+
if (companyName)
|
|
1462
|
+
vendor.CompanyName = companyName;
|
|
1463
|
+
if (givenName)
|
|
1464
|
+
vendor.GivenName = givenName;
|
|
1465
|
+
if (familyName)
|
|
1466
|
+
vendor.FamilyName = familyName;
|
|
1467
|
+
if (email)
|
|
1468
|
+
vendor.PrimaryEmailAddr = { Address: email };
|
|
1469
|
+
if (phone)
|
|
1470
|
+
vendor.PrimaryPhone = { FreeFormNumber: phone };
|
|
1471
|
+
return qbRequest('vendor', 'POST', vendor);
|
|
1472
|
+
}
|
|
1473
|
+
async function updateVendor(params) {
|
|
1474
|
+
const { vendorId, syncToken, displayName, email, phone, active } = params;
|
|
1475
|
+
if (!vendorId || !syncToken)
|
|
1476
|
+
throw new Error('vendorId and syncToken are required');
|
|
1477
|
+
const vendor = { Id: vendorId, SyncToken: syncToken, sparse: true };
|
|
1478
|
+
if (displayName)
|
|
1479
|
+
vendor.DisplayName = displayName;
|
|
1480
|
+
if (email)
|
|
1481
|
+
vendor.PrimaryEmailAddr = { Address: email };
|
|
1482
|
+
if (phone)
|
|
1483
|
+
vendor.PrimaryPhone = { FreeFormNumber: phone };
|
|
1484
|
+
if (active !== undefined)
|
|
1485
|
+
vendor.Active = active;
|
|
1486
|
+
return qbRequest('vendor', 'POST', vendor);
|
|
1487
|
+
}
|
|
1488
|
+
// --------------------------------------------------------------------------
|
|
1489
|
+
// BILLS
|
|
1490
|
+
// --------------------------------------------------------------------------
|
|
1491
|
+
async function listBills(params) {
|
|
1492
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1493
|
+
const offset = Number(params.offset) || 1;
|
|
1494
|
+
const vendorId = params.vendorId;
|
|
1495
|
+
const status = params.status;
|
|
1496
|
+
let query = `SELECT * FROM Bill`;
|
|
1497
|
+
const conditions = [];
|
|
1498
|
+
if (vendorId)
|
|
1499
|
+
conditions.push(`VendorRef = '${vendorId}'`);
|
|
1500
|
+
if (status) {
|
|
1501
|
+
if (status.toLowerCase() === 'paid')
|
|
1502
|
+
conditions.push(`Balance = '0'`);
|
|
1503
|
+
else if (status.toLowerCase() === 'unpaid')
|
|
1504
|
+
conditions.push(`Balance > '0'`);
|
|
1505
|
+
}
|
|
1506
|
+
if (conditions.length > 0)
|
|
1507
|
+
query += ` WHERE ${conditions.join(' AND ')}`;
|
|
1508
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1509
|
+
return qbQuery(query);
|
|
1510
|
+
}
|
|
1511
|
+
async function getBill(params) {
|
|
1512
|
+
const { billId } = params;
|
|
1513
|
+
if (!billId)
|
|
1514
|
+
throw new Error('billId is required');
|
|
1515
|
+
return qbRequest(`bill/${billId}`);
|
|
1516
|
+
}
|
|
1517
|
+
async function createBill(params) {
|
|
1518
|
+
const { vendorId, lineItems, dueDate, txnDate, privateNote } = params;
|
|
1519
|
+
if (!vendorId || !lineItems)
|
|
1520
|
+
throw new Error('vendorId and lineItems are required');
|
|
1521
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1522
|
+
Id: String(idx + 1),
|
|
1523
|
+
Amount: item.amount,
|
|
1524
|
+
Description: item.description,
|
|
1525
|
+
DetailType: 'AccountBasedExpenseLineDetail',
|
|
1526
|
+
AccountBasedExpenseLineDetail: { AccountRef: { value: item.accountId } },
|
|
1527
|
+
}));
|
|
1528
|
+
const bill = { VendorRef: { value: vendorId }, Line: lines };
|
|
1529
|
+
if (dueDate)
|
|
1530
|
+
bill.DueDate = dueDate;
|
|
1531
|
+
if (txnDate)
|
|
1532
|
+
bill.TxnDate = txnDate;
|
|
1533
|
+
if (privateNote)
|
|
1534
|
+
bill.PrivateNote = privateNote;
|
|
1535
|
+
return qbRequest('bill', 'POST', bill);
|
|
1536
|
+
}
|
|
1537
|
+
async function updateBill(params) {
|
|
1538
|
+
const { billId, syncToken, lineItems, dueDate } = params;
|
|
1539
|
+
if (!billId || !syncToken)
|
|
1540
|
+
throw new Error('billId and syncToken are required');
|
|
1541
|
+
const bill = { Id: billId, SyncToken: syncToken, sparse: true };
|
|
1542
|
+
if (lineItems) {
|
|
1543
|
+
bill.Line = lineItems.map((item, idx) => ({
|
|
1544
|
+
Id: String(idx + 1),
|
|
1545
|
+
Amount: item.amount,
|
|
1546
|
+
DetailType: 'AccountBasedExpenseLineDetail',
|
|
1547
|
+
AccountBasedExpenseLineDetail: { AccountRef: { value: item.accountId } },
|
|
1548
|
+
}));
|
|
1549
|
+
}
|
|
1550
|
+
if (dueDate)
|
|
1551
|
+
bill.DueDate = dueDate;
|
|
1552
|
+
return qbRequest('bill', 'POST', bill);
|
|
1553
|
+
}
|
|
1554
|
+
async function deleteBill(params) {
|
|
1555
|
+
const { billId, syncToken } = params;
|
|
1556
|
+
if (!billId || !syncToken)
|
|
1557
|
+
throw new Error('billId and syncToken are required');
|
|
1558
|
+
return qbRequest(`bill?operation=delete`, 'POST', { Id: billId, SyncToken: syncToken });
|
|
1559
|
+
}
|
|
1560
|
+
// --------------------------------------------------------------------------
|
|
1561
|
+
// BILL PAYMENTS
|
|
1562
|
+
// --------------------------------------------------------------------------
|
|
1563
|
+
async function listBillPayments(params) {
|
|
1564
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1565
|
+
const offset = Number(params.offset) || 1;
|
|
1566
|
+
return qbQuery(`SELECT * FROM BillPayment MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1567
|
+
}
|
|
1568
|
+
async function getBillPayment(params) {
|
|
1569
|
+
const { billPaymentId } = params;
|
|
1570
|
+
if (!billPaymentId)
|
|
1571
|
+
throw new Error('billPaymentId is required');
|
|
1572
|
+
return qbRequest(`billpayment/${billPaymentId}`);
|
|
1573
|
+
}
|
|
1574
|
+
async function createBillPayment(params) {
|
|
1575
|
+
const { vendorId, totalAmt, payType, billIds, bankAccountId, creditCardAccountId, txnDate } = params;
|
|
1576
|
+
if (!vendorId || totalAmt === undefined || !payType || !billIds) {
|
|
1577
|
+
throw new Error('vendorId, totalAmt, payType, and billIds are required');
|
|
1578
|
+
}
|
|
1579
|
+
const lines = billIds.map(billId => ({
|
|
1580
|
+
Amount: totalAmt / billIds.length,
|
|
1581
|
+
LinkedTxn: [{ TxnId: billId, TxnType: 'Bill' }],
|
|
1582
|
+
}));
|
|
1583
|
+
const payment = {
|
|
1584
|
+
VendorRef: { value: vendorId },
|
|
1585
|
+
TotalAmt: totalAmt,
|
|
1586
|
+
PayType: payType,
|
|
1587
|
+
Line: lines,
|
|
1588
|
+
};
|
|
1589
|
+
if (payType === 'Check' && bankAccountId) {
|
|
1590
|
+
payment.CheckPayment = { BankAccountRef: { value: bankAccountId } };
|
|
1591
|
+
}
|
|
1592
|
+
else if (payType === 'CreditCard' && creditCardAccountId) {
|
|
1593
|
+
payment.CreditCardPayment = { CCAccountRef: { value: creditCardAccountId } };
|
|
1594
|
+
}
|
|
1595
|
+
if (txnDate)
|
|
1596
|
+
payment.TxnDate = txnDate;
|
|
1597
|
+
return qbRequest('billpayment', 'POST', payment);
|
|
1598
|
+
}
|
|
1599
|
+
async function deleteBillPayment(params) {
|
|
1600
|
+
const { billPaymentId, syncToken } = params;
|
|
1601
|
+
if (!billPaymentId || !syncToken)
|
|
1602
|
+
throw new Error('billPaymentId and syncToken are required');
|
|
1603
|
+
return qbRequest(`billpayment?operation=delete`, 'POST', { Id: billPaymentId, SyncToken: syncToken });
|
|
1604
|
+
}
|
|
1605
|
+
// --------------------------------------------------------------------------
|
|
1606
|
+
// EXPENSES / PURCHASES
|
|
1607
|
+
// --------------------------------------------------------------------------
|
|
1608
|
+
async function listPurchases(params) {
|
|
1609
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1610
|
+
const offset = Number(params.offset) || 1;
|
|
1611
|
+
return qbQuery(`SELECT * FROM Purchase MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1612
|
+
}
|
|
1613
|
+
async function getPurchase(params) {
|
|
1614
|
+
const { purchaseId } = params;
|
|
1615
|
+
if (!purchaseId)
|
|
1616
|
+
throw new Error('purchaseId is required');
|
|
1617
|
+
return qbRequest(`purchase/${purchaseId}`);
|
|
1618
|
+
}
|
|
1619
|
+
async function createExpense(params) {
|
|
1620
|
+
const { paymentType, accountId, lineItems, vendorId, txnDate, privateNote } = params;
|
|
1621
|
+
if (!paymentType || !accountId || !lineItems) {
|
|
1622
|
+
throw new Error('paymentType, accountId, and lineItems are required');
|
|
1623
|
+
}
|
|
1624
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1625
|
+
Id: String(idx + 1),
|
|
1626
|
+
Amount: item.amount,
|
|
1627
|
+
Description: item.description,
|
|
1628
|
+
DetailType: 'AccountBasedExpenseLineDetail',
|
|
1629
|
+
AccountBasedExpenseLineDetail: { AccountRef: { value: item.accountId } },
|
|
1630
|
+
}));
|
|
1631
|
+
const expense = {
|
|
1632
|
+
PaymentType: paymentType,
|
|
1633
|
+
AccountRef: { value: accountId },
|
|
1634
|
+
Line: lines,
|
|
1635
|
+
};
|
|
1636
|
+
if (vendorId)
|
|
1637
|
+
expense.EntityRef = { value: vendorId, type: 'Vendor' };
|
|
1638
|
+
if (txnDate)
|
|
1639
|
+
expense.TxnDate = txnDate;
|
|
1640
|
+
if (privateNote)
|
|
1641
|
+
expense.PrivateNote = privateNote;
|
|
1642
|
+
return qbRequest('purchase', 'POST', expense);
|
|
1643
|
+
}
|
|
1644
|
+
async function deletePurchase(params) {
|
|
1645
|
+
const { purchaseId, syncToken } = params;
|
|
1646
|
+
if (!purchaseId || !syncToken)
|
|
1647
|
+
throw new Error('purchaseId and syncToken are required');
|
|
1648
|
+
return qbRequest(`purchase?operation=delete`, 'POST', { Id: purchaseId, SyncToken: syncToken });
|
|
1649
|
+
}
|
|
1650
|
+
// --------------------------------------------------------------------------
|
|
1651
|
+
// ITEMS
|
|
1652
|
+
// --------------------------------------------------------------------------
|
|
1653
|
+
async function listItems(params) {
|
|
1654
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1655
|
+
const offset = Number(params.offset) || 1;
|
|
1656
|
+
const type = params.type;
|
|
1657
|
+
const active = params.active;
|
|
1658
|
+
let query = `SELECT * FROM Item`;
|
|
1659
|
+
const conditions = [];
|
|
1660
|
+
if (type)
|
|
1661
|
+
conditions.push(`Type = '${type}'`);
|
|
1662
|
+
if (active !== undefined)
|
|
1663
|
+
conditions.push(`Active = ${active}`);
|
|
1664
|
+
if (conditions.length > 0)
|
|
1665
|
+
query += ` WHERE ${conditions.join(' AND ')}`;
|
|
1666
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1667
|
+
return qbQuery(query);
|
|
1668
|
+
}
|
|
1669
|
+
async function getItem(params) {
|
|
1670
|
+
const { itemId } = params;
|
|
1671
|
+
if (!itemId)
|
|
1672
|
+
throw new Error('itemId is required');
|
|
1673
|
+
return qbRequest(`item/${itemId}`);
|
|
1674
|
+
}
|
|
1675
|
+
async function createItem(params) {
|
|
1676
|
+
const { name, type, incomeAccountId, expenseAccountId, unitPrice, purchaseCost, description, purchaseDesc, qtyOnHand, assetAccountId } = params;
|
|
1677
|
+
if (!name || !type || !incomeAccountId)
|
|
1678
|
+
throw new Error('name, type, and incomeAccountId are required');
|
|
1679
|
+
const item = {
|
|
1680
|
+
Name: name,
|
|
1681
|
+
Type: type,
|
|
1682
|
+
IncomeAccountRef: { value: incomeAccountId },
|
|
1683
|
+
};
|
|
1684
|
+
if (expenseAccountId)
|
|
1685
|
+
item.ExpenseAccountRef = { value: expenseAccountId };
|
|
1686
|
+
if (unitPrice !== undefined)
|
|
1687
|
+
item.UnitPrice = unitPrice;
|
|
1688
|
+
if (purchaseCost !== undefined)
|
|
1689
|
+
item.PurchaseCost = purchaseCost;
|
|
1690
|
+
if (description)
|
|
1691
|
+
item.Description = description;
|
|
1692
|
+
if (purchaseDesc)
|
|
1693
|
+
item.PurchaseDesc = purchaseDesc;
|
|
1694
|
+
if (type === 'Inventory') {
|
|
1695
|
+
item.TrackQtyOnHand = true;
|
|
1696
|
+
item.QtyOnHand = qtyOnHand || 0;
|
|
1697
|
+
item.InvStartDate = new Date().toISOString().split('T')[0];
|
|
1698
|
+
if (assetAccountId)
|
|
1699
|
+
item.AssetAccountRef = { value: assetAccountId };
|
|
1700
|
+
}
|
|
1701
|
+
return qbRequest('item', 'POST', item);
|
|
1702
|
+
}
|
|
1703
|
+
async function updateItem(params) {
|
|
1704
|
+
const { itemId, syncToken, name, unitPrice, purchaseCost, description, active } = params;
|
|
1705
|
+
if (!itemId || !syncToken)
|
|
1706
|
+
throw new Error('itemId and syncToken are required');
|
|
1707
|
+
const item = { Id: itemId, SyncToken: syncToken, sparse: true };
|
|
1708
|
+
if (name)
|
|
1709
|
+
item.Name = name;
|
|
1710
|
+
if (unitPrice !== undefined)
|
|
1711
|
+
item.UnitPrice = unitPrice;
|
|
1712
|
+
if (purchaseCost !== undefined)
|
|
1713
|
+
item.PurchaseCost = purchaseCost;
|
|
1714
|
+
if (description)
|
|
1715
|
+
item.Description = description;
|
|
1716
|
+
if (active !== undefined)
|
|
1717
|
+
item.Active = active;
|
|
1718
|
+
return qbRequest('item', 'POST', item);
|
|
1719
|
+
}
|
|
1720
|
+
// --------------------------------------------------------------------------
|
|
1721
|
+
// ACCOUNTS
|
|
1722
|
+
// --------------------------------------------------------------------------
|
|
1723
|
+
async function listAccounts(params) {
|
|
1724
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1725
|
+
const accountType = params.accountType;
|
|
1726
|
+
const active = params.active;
|
|
1727
|
+
let query = `SELECT * FROM Account`;
|
|
1728
|
+
const conditions = [];
|
|
1729
|
+
if (accountType)
|
|
1730
|
+
conditions.push(`AccountType = '${accountType}'`);
|
|
1731
|
+
if (active !== undefined)
|
|
1732
|
+
conditions.push(`Active = ${active}`);
|
|
1733
|
+
if (conditions.length > 0)
|
|
1734
|
+
query += ` WHERE ${conditions.join(' AND ')}`;
|
|
1735
|
+
query += ` MAXRESULTS ${limit}`;
|
|
1736
|
+
return qbQuery(query);
|
|
1737
|
+
}
|
|
1738
|
+
async function getAccount(params) {
|
|
1739
|
+
const { accountId } = params;
|
|
1740
|
+
if (!accountId)
|
|
1741
|
+
throw new Error('accountId is required');
|
|
1742
|
+
return qbRequest(`account/${accountId}`);
|
|
1743
|
+
}
|
|
1744
|
+
async function createAccount(params) {
|
|
1745
|
+
const { name, accountType, accountSubType, description } = params;
|
|
1746
|
+
if (!name || !accountType)
|
|
1747
|
+
throw new Error('name and accountType are required');
|
|
1748
|
+
const account = { Name: name, AccountType: accountType };
|
|
1749
|
+
if (accountSubType)
|
|
1750
|
+
account.AccountSubType = accountSubType;
|
|
1751
|
+
if (description)
|
|
1752
|
+
account.Description = description;
|
|
1753
|
+
return qbRequest('account', 'POST', account);
|
|
1754
|
+
}
|
|
1755
|
+
async function updateAccount(params) {
|
|
1756
|
+
const { accountId, syncToken, name, description, active } = params;
|
|
1757
|
+
if (!accountId || !syncToken)
|
|
1758
|
+
throw new Error('accountId and syncToken are required');
|
|
1759
|
+
const account = { Id: accountId, SyncToken: syncToken, sparse: true };
|
|
1760
|
+
if (name)
|
|
1761
|
+
account.Name = name;
|
|
1762
|
+
if (description)
|
|
1763
|
+
account.Description = description;
|
|
1764
|
+
if (active !== undefined)
|
|
1765
|
+
account.Active = active;
|
|
1766
|
+
return qbRequest('account', 'POST', account);
|
|
1767
|
+
}
|
|
1768
|
+
// --------------------------------------------------------------------------
|
|
1769
|
+
// EMPLOYEES
|
|
1770
|
+
// --------------------------------------------------------------------------
|
|
1771
|
+
async function listEmployees(params) {
|
|
1772
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1773
|
+
const offset = Number(params.offset) || 1;
|
|
1774
|
+
const active = params.active;
|
|
1775
|
+
let query = `SELECT * FROM Employee`;
|
|
1776
|
+
if (active !== undefined)
|
|
1777
|
+
query += ` WHERE Active = ${active}`;
|
|
1778
|
+
query += ` MAXRESULTS ${limit} STARTPOSITION ${offset}`;
|
|
1779
|
+
return qbQuery(query);
|
|
1780
|
+
}
|
|
1781
|
+
async function getEmployee(params) {
|
|
1782
|
+
const { employeeId } = params;
|
|
1783
|
+
if (!employeeId)
|
|
1784
|
+
throw new Error('employeeId is required');
|
|
1785
|
+
return qbRequest(`employee/${employeeId}`);
|
|
1786
|
+
}
|
|
1787
|
+
async function createEmployee(params) {
|
|
1788
|
+
const { displayName, givenName, familyName, email, phone } = params;
|
|
1789
|
+
if (!displayName)
|
|
1790
|
+
throw new Error('displayName is required');
|
|
1791
|
+
const employee = { DisplayName: displayName };
|
|
1792
|
+
if (givenName)
|
|
1793
|
+
employee.GivenName = givenName;
|
|
1794
|
+
if (familyName)
|
|
1795
|
+
employee.FamilyName = familyName;
|
|
1796
|
+
if (email)
|
|
1797
|
+
employee.PrimaryEmailAddr = { Address: email };
|
|
1798
|
+
if (phone)
|
|
1799
|
+
employee.PrimaryPhone = { FreeFormNumber: phone };
|
|
1800
|
+
return qbRequest('employee', 'POST', employee);
|
|
1801
|
+
}
|
|
1802
|
+
async function updateEmployee(params) {
|
|
1803
|
+
const { employeeId, syncToken, displayName, email, phone, active } = params;
|
|
1804
|
+
if (!employeeId || !syncToken)
|
|
1805
|
+
throw new Error('employeeId and syncToken are required');
|
|
1806
|
+
const employee = { Id: employeeId, SyncToken: syncToken, sparse: true };
|
|
1807
|
+
if (displayName)
|
|
1808
|
+
employee.DisplayName = displayName;
|
|
1809
|
+
if (email)
|
|
1810
|
+
employee.PrimaryEmailAddr = { Address: email };
|
|
1811
|
+
if (phone)
|
|
1812
|
+
employee.PrimaryPhone = { FreeFormNumber: phone };
|
|
1813
|
+
if (active !== undefined)
|
|
1814
|
+
employee.Active = active;
|
|
1815
|
+
return qbRequest('employee', 'POST', employee);
|
|
1816
|
+
}
|
|
1817
|
+
// --------------------------------------------------------------------------
|
|
1818
|
+
// JOURNAL ENTRIES
|
|
1819
|
+
// --------------------------------------------------------------------------
|
|
1820
|
+
async function listJournalEntries(params) {
|
|
1821
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1822
|
+
const offset = Number(params.offset) || 1;
|
|
1823
|
+
return qbQuery(`SELECT * FROM JournalEntry MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1824
|
+
}
|
|
1825
|
+
async function getJournalEntry(params) {
|
|
1826
|
+
const { journalEntryId } = params;
|
|
1827
|
+
if (!journalEntryId)
|
|
1828
|
+
throw new Error('journalEntryId is required');
|
|
1829
|
+
return qbRequest(`journalentry/${journalEntryId}`);
|
|
1830
|
+
}
|
|
1831
|
+
async function createJournalEntry(params) {
|
|
1832
|
+
const { lineItems, txnDate, privateNote } = params;
|
|
1833
|
+
if (!lineItems)
|
|
1834
|
+
throw new Error('lineItems is required');
|
|
1835
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1836
|
+
Id: String(idx + 1),
|
|
1837
|
+
Amount: item.amount,
|
|
1838
|
+
Description: item.description,
|
|
1839
|
+
DetailType: 'JournalEntryLineDetail',
|
|
1840
|
+
JournalEntryLineDetail: {
|
|
1841
|
+
PostingType: item.postingType,
|
|
1842
|
+
AccountRef: { value: item.accountId },
|
|
1843
|
+
},
|
|
1844
|
+
}));
|
|
1845
|
+
const entry = { Line: lines };
|
|
1846
|
+
if (txnDate)
|
|
1847
|
+
entry.TxnDate = txnDate;
|
|
1848
|
+
if (privateNote)
|
|
1849
|
+
entry.PrivateNote = privateNote;
|
|
1850
|
+
return qbRequest('journalentry', 'POST', entry);
|
|
1851
|
+
}
|
|
1852
|
+
async function deleteJournalEntry(params) {
|
|
1853
|
+
const { journalEntryId, syncToken } = params;
|
|
1854
|
+
if (!journalEntryId || !syncToken)
|
|
1855
|
+
throw new Error('journalEntryId and syncToken are required');
|
|
1856
|
+
return qbRequest(`journalentry?operation=delete`, 'POST', { Id: journalEntryId, SyncToken: syncToken });
|
|
1857
|
+
}
|
|
1858
|
+
// --------------------------------------------------------------------------
|
|
1859
|
+
// DEPOSITS
|
|
1860
|
+
// --------------------------------------------------------------------------
|
|
1861
|
+
async function listDeposits(params) {
|
|
1862
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1863
|
+
const offset = Number(params.offset) || 1;
|
|
1864
|
+
return qbQuery(`SELECT * FROM Deposit MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1865
|
+
}
|
|
1866
|
+
async function getDeposit(params) {
|
|
1867
|
+
const { depositId } = params;
|
|
1868
|
+
if (!depositId)
|
|
1869
|
+
throw new Error('depositId is required');
|
|
1870
|
+
return qbRequest(`deposit/${depositId}`);
|
|
1871
|
+
}
|
|
1872
|
+
async function createDeposit(params) {
|
|
1873
|
+
const { depositToAccountId, lineItems, txnDate } = params;
|
|
1874
|
+
if (!depositToAccountId || !lineItems)
|
|
1875
|
+
throw new Error('depositToAccountId and lineItems are required');
|
|
1876
|
+
const lines = lineItems.map((item, idx) => ({
|
|
1877
|
+
Id: String(idx + 1),
|
|
1878
|
+
Amount: item.amount,
|
|
1879
|
+
Description: item.description,
|
|
1880
|
+
DetailType: 'DepositLineDetail',
|
|
1881
|
+
DepositLineDetail: { AccountRef: { value: item.accountId } },
|
|
1882
|
+
}));
|
|
1883
|
+
const deposit = {
|
|
1884
|
+
DepositToAccountRef: { value: depositToAccountId },
|
|
1885
|
+
Line: lines,
|
|
1886
|
+
};
|
|
1887
|
+
if (txnDate)
|
|
1888
|
+
deposit.TxnDate = txnDate;
|
|
1889
|
+
return qbRequest('deposit', 'POST', deposit);
|
|
1890
|
+
}
|
|
1891
|
+
async function deleteDeposit(params) {
|
|
1892
|
+
const { depositId, syncToken } = params;
|
|
1893
|
+
if (!depositId || !syncToken)
|
|
1894
|
+
throw new Error('depositId and syncToken are required');
|
|
1895
|
+
return qbRequest(`deposit?operation=delete`, 'POST', { Id: depositId, SyncToken: syncToken });
|
|
1896
|
+
}
|
|
1897
|
+
// --------------------------------------------------------------------------
|
|
1898
|
+
// TRANSFERS
|
|
1899
|
+
// --------------------------------------------------------------------------
|
|
1900
|
+
async function listTransfers(params) {
|
|
1901
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1902
|
+
const offset = Number(params.offset) || 1;
|
|
1903
|
+
return qbQuery(`SELECT * FROM Transfer MAXRESULTS ${limit} STARTPOSITION ${offset}`);
|
|
1904
|
+
}
|
|
1905
|
+
async function getTransfer(params) {
|
|
1906
|
+
const { transferId } = params;
|
|
1907
|
+
if (!transferId)
|
|
1908
|
+
throw new Error('transferId is required');
|
|
1909
|
+
return qbRequest(`transfer/${transferId}`);
|
|
1910
|
+
}
|
|
1911
|
+
async function createTransfer(params) {
|
|
1912
|
+
const { fromAccountId, toAccountId, amount, txnDate, privateNote } = params;
|
|
1913
|
+
if (!fromAccountId || !toAccountId || amount === undefined) {
|
|
1914
|
+
throw new Error('fromAccountId, toAccountId, and amount are required');
|
|
1915
|
+
}
|
|
1916
|
+
const transfer = {
|
|
1917
|
+
FromAccountRef: { value: fromAccountId },
|
|
1918
|
+
ToAccountRef: { value: toAccountId },
|
|
1919
|
+
Amount: amount,
|
|
1920
|
+
};
|
|
1921
|
+
if (txnDate)
|
|
1922
|
+
transfer.TxnDate = txnDate;
|
|
1923
|
+
if (privateNote)
|
|
1924
|
+
transfer.PrivateNote = privateNote;
|
|
1925
|
+
return qbRequest('transfer', 'POST', transfer);
|
|
1926
|
+
}
|
|
1927
|
+
async function deleteTransfer(params) {
|
|
1928
|
+
const { transferId, syncToken } = params;
|
|
1929
|
+
if (!transferId || !syncToken)
|
|
1930
|
+
throw new Error('transferId and syncToken are required');
|
|
1931
|
+
return qbRequest(`transfer?operation=delete`, 'POST', { Id: transferId, SyncToken: syncToken });
|
|
1932
|
+
}
|
|
1933
|
+
// --------------------------------------------------------------------------
|
|
1934
|
+
// TAX
|
|
1935
|
+
// --------------------------------------------------------------------------
|
|
1936
|
+
async function listTaxCodes(params) {
|
|
1937
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1938
|
+
return qbQuery(`SELECT * FROM TaxCode MAXRESULTS ${limit}`);
|
|
1939
|
+
}
|
|
1940
|
+
async function listTaxRates(params) {
|
|
1941
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1942
|
+
return qbQuery(`SELECT * FROM TaxRate MAXRESULTS ${limit}`);
|
|
1943
|
+
}
|
|
1944
|
+
// --------------------------------------------------------------------------
|
|
1945
|
+
// PAYMENT METHODS
|
|
1946
|
+
// --------------------------------------------------------------------------
|
|
1947
|
+
async function listPaymentMethods(params) {
|
|
1948
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1949
|
+
return qbQuery(`SELECT * FROM PaymentMethod MAXRESULTS ${limit}`);
|
|
1950
|
+
}
|
|
1951
|
+
// --------------------------------------------------------------------------
|
|
1952
|
+
// TERMS
|
|
1953
|
+
// --------------------------------------------------------------------------
|
|
1954
|
+
async function listTerms(params) {
|
|
1955
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1956
|
+
return qbQuery(`SELECT * FROM Term MAXRESULTS ${limit}`);
|
|
1957
|
+
}
|
|
1958
|
+
// --------------------------------------------------------------------------
|
|
1959
|
+
// CLASSES / DEPARTMENTS
|
|
1960
|
+
// --------------------------------------------------------------------------
|
|
1961
|
+
async function listClasses(params) {
|
|
1962
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1963
|
+
return qbQuery(`SELECT * FROM Class MAXRESULTS ${limit}`);
|
|
1964
|
+
}
|
|
1965
|
+
async function listDepartments(params) {
|
|
1966
|
+
const limit = Math.min(Number(params.limit) || 100, 1000);
|
|
1967
|
+
return qbQuery(`SELECT * FROM Department MAXRESULTS ${limit}`);
|
|
1968
|
+
}
|
|
1969
|
+
// --------------------------------------------------------------------------
|
|
1970
|
+
// REPORTS
|
|
1971
|
+
// --------------------------------------------------------------------------
|
|
1972
|
+
async function getReport(reportName, params) {
|
|
1973
|
+
const queryParams = [];
|
|
1974
|
+
if (params.startDate)
|
|
1975
|
+
queryParams.push(`start_date=${params.startDate}`);
|
|
1976
|
+
if (params.endDate)
|
|
1977
|
+
queryParams.push(`end_date=${params.endDate}`);
|
|
1978
|
+
if (params.reportDate)
|
|
1979
|
+
queryParams.push(`report_date=${params.reportDate}`);
|
|
1980
|
+
if (params.summarizeBy)
|
|
1981
|
+
queryParams.push(`summarize_column_by=${params.summarizeBy}`);
|
|
1982
|
+
if (params.agingMethod)
|
|
1983
|
+
queryParams.push(`aging_method=${params.agingMethod}`);
|
|
1984
|
+
const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';
|
|
1985
|
+
return qbRequest(`reports/${reportName}${queryString}`);
|
|
1986
|
+
}
|
|
1987
|
+
async function getProfitLossReport(params) {
|
|
1988
|
+
return getReport('ProfitAndLoss', params);
|
|
1989
|
+
}
|
|
1990
|
+
async function getBalanceSheetReport(params) {
|
|
1991
|
+
return getReport('BalanceSheet', params);
|
|
1992
|
+
}
|
|
1993
|
+
async function getCashFlowReport(params) {
|
|
1994
|
+
return getReport('CashFlow', params);
|
|
1995
|
+
}
|
|
1996
|
+
async function getArAgingReport(params) {
|
|
1997
|
+
return getReport('AgedReceivables', params);
|
|
1998
|
+
}
|
|
1999
|
+
async function getApAgingReport(params) {
|
|
2000
|
+
return getReport('AgedPayables', params);
|
|
2001
|
+
}
|
|
2002
|
+
async function getCustomerBalanceReport(params) {
|
|
2003
|
+
return getReport('CustomerBalance', params);
|
|
2004
|
+
}
|
|
2005
|
+
async function getVendorBalanceReport(params) {
|
|
2006
|
+
return getReport('VendorBalance', params);
|
|
2007
|
+
}
|
|
2008
|
+
async function getGeneralLedgerReport(params) {
|
|
2009
|
+
return getReport('GeneralLedger', params);
|
|
2010
|
+
}
|
|
2011
|
+
async function getTrialBalanceReport(params) {
|
|
2012
|
+
return getReport('TrialBalance', params);
|
|
2013
|
+
}
|
|
2014
|
+
// --------------------------------------------------------------------------
|
|
2015
|
+
// RAW QUERY
|
|
2016
|
+
// --------------------------------------------------------------------------
|
|
2017
|
+
async function runQuery(params) {
|
|
2018
|
+
const { query } = params;
|
|
2019
|
+
if (!query || typeof query !== 'string') {
|
|
2020
|
+
throw new Error('query is required and must be a string');
|
|
2021
|
+
}
|
|
2022
|
+
if (!query.trim().toUpperCase().startsWith('SELECT')) {
|
|
2023
|
+
throw new Error('Only SELECT queries are allowed');
|
|
2024
|
+
}
|
|
2025
|
+
return qbQuery(query);
|
|
2026
|
+
}
|
|
2027
|
+
// ============================================================================
|
|
2028
|
+
// BACKEND EXPORT
|
|
2029
|
+
// ============================================================================
|
|
2030
|
+
export const quickbooksBackend = {
|
|
2031
|
+
name: 'quickbooks',
|
|
2032
|
+
description: 'Comprehensive QuickBooks Online accounting integration: customers, invoices, estimates, payments, bills, vendors, items, accounts, employees, journal entries, reports, and more.',
|
|
2033
|
+
actions,
|
|
2034
|
+
async execute(action, params) {
|
|
2035
|
+
switch (action) {
|
|
2036
|
+
// Company
|
|
2037
|
+
case 'get_company_info': return getCompanyInfo();
|
|
2038
|
+
case 'get_preferences': return getPreferences();
|
|
2039
|
+
// Customers
|
|
2040
|
+
case 'list_customers': return listCustomers(params);
|
|
2041
|
+
case 'get_customer': return getCustomer(params);
|
|
2042
|
+
case 'create_customer': return createCustomer(params);
|
|
2043
|
+
case 'update_customer': return updateCustomer(params);
|
|
2044
|
+
// Invoices
|
|
2045
|
+
case 'list_invoices': return listInvoices(params);
|
|
2046
|
+
case 'get_invoice': return getInvoice(params);
|
|
2047
|
+
case 'create_invoice': return createInvoice(params);
|
|
2048
|
+
case 'update_invoice': return updateInvoice(params);
|
|
2049
|
+
case 'delete_invoice': return deleteInvoice(params);
|
|
2050
|
+
case 'send_invoice': return sendInvoice(params);
|
|
2051
|
+
case 'void_invoice': return voidInvoice(params);
|
|
2052
|
+
// Estimates
|
|
2053
|
+
case 'list_estimates': return listEstimates(params);
|
|
2054
|
+
case 'get_estimate': return getEstimate(params);
|
|
2055
|
+
case 'create_estimate': return createEstimate(params);
|
|
2056
|
+
case 'update_estimate': return updateEstimate(params);
|
|
2057
|
+
case 'delete_estimate': return deleteEstimate(params);
|
|
2058
|
+
case 'send_estimate': return sendEstimate(params);
|
|
2059
|
+
// Payments
|
|
2060
|
+
case 'list_payments': return listPayments(params);
|
|
2061
|
+
case 'get_payment': return getPayment(params);
|
|
2062
|
+
case 'create_payment': return createPayment(params);
|
|
2063
|
+
case 'update_payment': return updatePayment(params);
|
|
2064
|
+
case 'delete_payment': return deletePayment(params);
|
|
2065
|
+
case 'void_payment': return voidPayment(params);
|
|
2066
|
+
// Sales Receipts
|
|
2067
|
+
case 'list_sales_receipts': return listSalesReceipts(params);
|
|
2068
|
+
case 'get_sales_receipt': return getSalesReceipt(params);
|
|
2069
|
+
case 'create_sales_receipt': return createSalesReceipt(params);
|
|
2070
|
+
case 'delete_sales_receipt': return deleteSalesReceipt(params);
|
|
2071
|
+
// Credit Memos
|
|
2072
|
+
case 'list_credit_memos': return listCreditMemos(params);
|
|
2073
|
+
case 'get_credit_memo': return getCreditMemo(params);
|
|
2074
|
+
case 'create_credit_memo': return createCreditMemo(params);
|
|
2075
|
+
case 'delete_credit_memo': return deleteCreditMemo(params);
|
|
2076
|
+
// Refund Receipts
|
|
2077
|
+
case 'list_refund_receipts': return listRefundReceipts(params);
|
|
2078
|
+
case 'get_refund_receipt': return getRefundReceipt(params);
|
|
2079
|
+
case 'create_refund_receipt': return createRefundReceipt(params);
|
|
2080
|
+
case 'delete_refund_receipt': return deleteRefundReceipt(params);
|
|
2081
|
+
// Vendors
|
|
2082
|
+
case 'list_vendors': return listVendors(params);
|
|
2083
|
+
case 'get_vendor': return getVendor(params);
|
|
2084
|
+
case 'create_vendor': return createVendor(params);
|
|
2085
|
+
case 'update_vendor': return updateVendor(params);
|
|
2086
|
+
// Bills
|
|
2087
|
+
case 'list_bills': return listBills(params);
|
|
2088
|
+
case 'get_bill': return getBill(params);
|
|
2089
|
+
case 'create_bill': return createBill(params);
|
|
2090
|
+
case 'update_bill': return updateBill(params);
|
|
2091
|
+
case 'delete_bill': return deleteBill(params);
|
|
2092
|
+
// Bill Payments
|
|
2093
|
+
case 'list_bill_payments': return listBillPayments(params);
|
|
2094
|
+
case 'get_bill_payment': return getBillPayment(params);
|
|
2095
|
+
case 'create_bill_payment': return createBillPayment(params);
|
|
2096
|
+
case 'delete_bill_payment': return deleteBillPayment(params);
|
|
2097
|
+
// Expenses / Purchases
|
|
2098
|
+
case 'list_purchases': return listPurchases(params);
|
|
2099
|
+
case 'get_purchase': return getPurchase(params);
|
|
2100
|
+
case 'create_expense': return createExpense(params);
|
|
2101
|
+
case 'delete_purchase': return deletePurchase(params);
|
|
2102
|
+
// Items
|
|
2103
|
+
case 'list_items': return listItems(params);
|
|
2104
|
+
case 'get_item': return getItem(params);
|
|
2105
|
+
case 'create_item': return createItem(params);
|
|
2106
|
+
case 'update_item': return updateItem(params);
|
|
2107
|
+
// Accounts
|
|
2108
|
+
case 'list_accounts': return listAccounts(params);
|
|
2109
|
+
case 'get_account': return getAccount(params);
|
|
2110
|
+
case 'create_account': return createAccount(params);
|
|
2111
|
+
case 'update_account': return updateAccount(params);
|
|
2112
|
+
// Employees
|
|
2113
|
+
case 'list_employees': return listEmployees(params);
|
|
2114
|
+
case 'get_employee': return getEmployee(params);
|
|
2115
|
+
case 'create_employee': return createEmployee(params);
|
|
2116
|
+
case 'update_employee': return updateEmployee(params);
|
|
2117
|
+
// Journal Entries
|
|
2118
|
+
case 'list_journal_entries': return listJournalEntries(params);
|
|
2119
|
+
case 'get_journal_entry': return getJournalEntry(params);
|
|
2120
|
+
case 'create_journal_entry': return createJournalEntry(params);
|
|
2121
|
+
case 'delete_journal_entry': return deleteJournalEntry(params);
|
|
2122
|
+
// Deposits
|
|
2123
|
+
case 'list_deposits': return listDeposits(params);
|
|
2124
|
+
case 'get_deposit': return getDeposit(params);
|
|
2125
|
+
case 'create_deposit': return createDeposit(params);
|
|
2126
|
+
case 'delete_deposit': return deleteDeposit(params);
|
|
2127
|
+
// Transfers
|
|
2128
|
+
case 'list_transfers': return listTransfers(params);
|
|
2129
|
+
case 'get_transfer': return getTransfer(params);
|
|
2130
|
+
case 'create_transfer': return createTransfer(params);
|
|
2131
|
+
case 'delete_transfer': return deleteTransfer(params);
|
|
2132
|
+
// Tax
|
|
2133
|
+
case 'list_tax_codes': return listTaxCodes(params);
|
|
2134
|
+
case 'list_tax_rates': return listTaxRates(params);
|
|
2135
|
+
// Payment Methods
|
|
2136
|
+
case 'list_payment_methods': return listPaymentMethods(params);
|
|
2137
|
+
// Terms
|
|
2138
|
+
case 'list_terms': return listTerms(params);
|
|
2139
|
+
// Classes / Departments
|
|
2140
|
+
case 'list_classes': return listClasses(params);
|
|
2141
|
+
case 'list_departments': return listDepartments(params);
|
|
2142
|
+
// Reports
|
|
2143
|
+
case 'get_profit_loss_report': return getProfitLossReport(params);
|
|
2144
|
+
case 'get_balance_sheet_report': return getBalanceSheetReport(params);
|
|
2145
|
+
case 'get_cash_flow_report': return getCashFlowReport(params);
|
|
2146
|
+
case 'get_ar_aging_report': return getArAgingReport(params);
|
|
2147
|
+
case 'get_ap_aging_report': return getApAgingReport(params);
|
|
2148
|
+
case 'get_customer_balance_report': return getCustomerBalanceReport(params);
|
|
2149
|
+
case 'get_vendor_balance_report': return getVendorBalanceReport(params);
|
|
2150
|
+
case 'get_general_ledger_report': return getGeneralLedgerReport(params);
|
|
2151
|
+
case 'get_trial_balance_report': return getTrialBalanceReport(params);
|
|
2152
|
+
// Query
|
|
2153
|
+
case 'query': return runQuery(params);
|
|
2154
|
+
default:
|
|
2155
|
+
throw new Error(`Unknown action: ${action}`);
|
|
2156
|
+
}
|
|
2157
|
+
},
|
|
2158
|
+
async healthCheck() {
|
|
2159
|
+
const startTime = Date.now();
|
|
2160
|
+
try {
|
|
2161
|
+
if (!CLIENT_ID || !CLIENT_SECRET || !refreshToken || !REALM_ID) {
|
|
2162
|
+
return {
|
|
2163
|
+
status: 'unavailable',
|
|
2164
|
+
latency_ms: Date.now() - startTime,
|
|
2165
|
+
error: 'QuickBooks credentials not configured',
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
await getCompanyInfo();
|
|
2169
|
+
return {
|
|
2170
|
+
status: 'healthy',
|
|
2171
|
+
latency_ms: Date.now() - startTime,
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
catch (error) {
|
|
2175
|
+
return {
|
|
2176
|
+
status: 'unavailable',
|
|
2177
|
+
latency_ms: Date.now() - startTime,
|
|
2178
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
},
|
|
2182
|
+
};
|
|
2183
|
+
//# sourceMappingURL=quickbooks.js.map
|