From 2ef2c0edbf21c424709ad6cfa6ea38b554b33efc Mon Sep 17 00:00:00 2001 From: seb Date: Tue, 13 Oct 2026 01:30:11 +0200 Subject: [PATCH] u --- API.md | 2 +- API.order.md | 12 +- scripts/test-order-filters.js | 205 +++++++++++++++++++++++++++++++ src/store/order/list.js | 222 +++++++++++++++++++++++++++++++--- 4 files changed, 416 insertions(+), 25 deletions(-) create mode 100644 scripts/test-order-filters.js diff --git a/API.md b/API.md index 42017b3..a3d808c 100644 --- a/API.md +++ b/API.md @@ -184,7 +184,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met - `create(googleAuthId: number, body: {number: string, date: string, entityId?: number, externalNumber?: string, lines?: Array<{sku?: string, name?: string, pu?: number, amount: number, net: number, rebate?: number, taxrate: number, comment?: string|null}>}, tx?: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>` - `delete(googleAuthId: number, id: number, tx?: object): Promise` - `getById(googleAuthId: number, id: number, tx?: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>` - - `list(googleAuthId: number, opts?: {offset?: number, limit?: number}, tx?: object): Promise<{orders: Array<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, createdAt: string|null, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>, total: number, offset: number, limit: number}|Array>` + - `list(googleAuthId: number, opts?: {offset?: number, limit?: number, search?: string, onlyUnpaid?: boolean, onlyUndelivered?: boolean, seekMonths?: number}, tx?: object): Promise<{orders: Array<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, createdAt: string|null, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>, total: number, offset: number, limit: number}|Array>` - `update(googleAuthId: number, id: number, patch: {number?: string, date?: string, entityId?: number, externalNumber?: string, lines?: Array<{sku?: string, name?: string, pu?: number, amount: number, net: number, rebate?: number, taxrate: number, comment?: string|null}>}, tx?: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>` - [shipment](API.shipment.md) - `create(provider: import('../../providers/provider.js').DatabaseProvider): void` diff --git a/API.order.md b/API.order.md index 232dcc2..91731fc 100644 --- a/API.order.md +++ b/API.order.md @@ -104,9 +104,13 @@ Lists the orders of the user's selected company. | Name | Type | Description | | --- | --- | --- | | `googleAuthId` | `number` | The id of the Google auth user. | -| `[opts]` | `object` | Optional pagination options. | +| `[opts]` | `object` | Optional pagination and filter options. | | `[opts.offset=0]` | `number` | Number of orders to skip. | -| `[opts.limit=20]` | `number` | Number of orders to return. | +| `[opts.limit=50]` | `number` | Number of orders to return. | +| `[opts.search]` | `string` | Free-text search matching order number, external number, or customer name. | +| `[opts.onlyUnpaid=false]` | `boolean` | When true, returns only unpaid orders. | +| `[opts.onlyUndelivered=false]` | `boolean` | When true, returns only undelivered orders. | +| `[opts.seekMonths]` | `number` | Negative integer for cutoff months ago (e.g. -1). | | `[tx]` | `object` | Optional transaction. | **Returns** @@ -116,8 +120,8 @@ Lists the orders of the user's selected company. **Example** ```js -const result = await store.order.list(42, { offset: 0, limit: 20 }); -// => { orders: [...], total: 100, offset: 0, limit: 20 } +const result = await store.order.list(42, { offset: 0, limit: 50, search: '1002', onlyUnpaid: true, onlyUndelivered: true, seekMonths: -1 }); +// => { orders: [...], total: 10, offset: 0, limit: 50 } const orders = await store.order.list(42); // => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }] diff --git a/scripts/test-order-filters.js b/scripts/test-order-filters.js new file mode 100644 index 0000000..7cd5799 --- /dev/null +++ b/scripts/test-order-filters.js @@ -0,0 +1,205 @@ +import assert from 'node:assert/strict'; +import { mkdtempSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import LibDashStore from '../src/index.js'; +import { BetterSqlite3Provider } from '../src/providers/sqlite3/index.js'; + +async function run() { + console.log('--- Testing Order Filtering & Paging in dashdbschema ---'); + + const tempDir = mkdtempSync(join(tmpdir(), 'test-order-filters-')); + const dbFile = join(tempDir, 'test.db'); + const storageDir = join(tempDir, 'storage'); + + const provider = new BetterSqlite3Provider({ + filename: dbFile, + storageDir, + }); + + await provider.initialize(); + const store = await new LibDashStore(provider); + + try { + const googleAuthId = await store.google_auth.add('filter-test@example.com'); + const company = await store.company.create({ + name: 'Filter Test Corp', + iso639: 'de', + taxrate: 19, + reducedtaxrate: 7, + googleAuthId, + }); + await store.google_auth.setSelectedCompany(googleAuthId, company.id); + + const warehouse = await store.warehouse.create(googleAuthId, { name: 'Hauptlager' }); + await store.unit.upsert(googleAuthId, { + si: 'stk', + basesi: 'stk', + basesifactor: 1, + symbol: 'Stk', + name: 'Stück', + }); + + const groups = await store.customergroup.list(googleAuthId); + const customerAlice = await store.entity.create(googleAuthId, { + customergroupId: groups[0].id, + firstName: 'Alice', + name: 'Wonderland', + }); + const customerBob = await store.entity.create(googleAuthId, { + customergroupId: groups[0].id, + firstName: 'Bob', + name: 'Builder', + }); + + const art = await store.article.createUnderParent({ + googleAuthId, + parentId: company.rootCategoryId, + name: 'Widget', + track_stock: 1, + }); + await store.stock.adjust(googleAuthId, { + sku: art.sku, + warehouseId: warehouse.id, + amount: 100, + text: 'Stock in', + }); + + // Account for payments + const account = await store.account.create(googleAuthId, { + name: 'Bank', + type: 'bank', + }); + + // Create 3 orders + // Order 1: Alice, O-1001, €119 (1 * 100 + 19% tax), Date: 2 months ago (2026-08-01) + // Paid in full, Unshipped + const order1 = await store.order.create(googleAuthId, { + number: 'O-1001', + date: '2026-08-01T10:00:00Z', + entityId: customerAlice.id, + lines: [{ sku: art.sku, name: 'Widget', amount: 1, net: 100, taxrate: 19 }], + }); + await store.payment.create(googleAuthId, { + accountId: account.id, + manifestId: order1.id, + type: 'bank_transfer', + amount: 119, + }); + + // Order 2: Bob, O-1002, €238 (2 * 100 + 19% tax), Date: 10 days ago (2026-10-03) + // Unpaid, Shipped in full with shipping 'shipped' + const order2 = await store.order.create(googleAuthId, { + number: 'O-1002', + date: '2026-10-03T10:00:00Z', + entityId: customerBob.id, + lines: [{ sku: art.sku, name: 'Widget', amount: 2, net: 100, taxrate: 19 }], + }); + const shipment2 = await store.shipment.create(googleAuthId, { + orderId: order2.id, + lines: [{ sku: art.sku, amount: 2 }], + }); + await store.shipping.create(googleAuthId, { + manifestId: shipment2.id, + type: 'parcel', + state: 'shipped', + }); + + // Order 3: Alice, O-1003, €59.50, Date: today (2026-10-13) + // Unpaid, Undelivered + const order3 = await store.order.create(googleAuthId, { + number: 'O-1003', + date: '2026-10-13T10:00:00Z', + entityId: customerAlice.id, + lines: [{ sku: art.sku, name: 'Widget', amount: 1, net: 50, taxrate: 19 }], + }); + + // Order 4: Bob, O-1004, €119 (1 * 100 + 19% tax), Date: today (2026-10-13) + // Overpaid (paid €150), Delivered + const order4 = await store.order.create(googleAuthId, { + number: 'O-1004', + date: '2026-10-13T10:00:00Z', + entityId: customerBob.id, + lines: [{ sku: art.sku, name: 'Widget', amount: 1, net: 100, taxrate: 19 }], + }); + await store.payment.create(googleAuthId, { + accountId: account.id, + manifestId: order4.id, + type: 'bank_transfer', + amount: 150, // Overpaid! + }); + const shipment4 = await store.shipment.create(googleAuthId, { + orderId: order4.id, + lines: [{ sku: art.sku, amount: 1 }], + }); + await store.shipping.create(googleAuthId, { + manifestId: shipment4.id, + type: 'parcel', + state: 'shipped', + }); + + console.log('Orders created successfully.'); + + // 1. Search Alice + const resAlice = await store.order.list(googleAuthId, { search: 'Alice' }); + assert.equal(resAlice.total, 2, 'Should find 2 orders for Alice'); + assert.deepEqual(resAlice.orders.map((o) => o.number), ['O-1003', 'O-1001']); + + // 2. Search Bob + const resBob = await store.order.list(googleAuthId, { search: 'Bob' }); + assert.equal(resBob.total, 2, 'Should find 2 orders for Bob'); + assert.deepEqual(resBob.orders.map((o) => o.number), ['O-1004', 'O-1002']); + + // 3. Search 1002 + const res1002 = await store.order.list(googleAuthId, { search: '1002' }); + assert.equal(res1002.total, 1, 'Should find 1 order for 1002'); + assert.equal(res1002.orders[0].number, 'O-1002'); + + // 4. onlyUnpaid (O-1004 is overpaid, so it also counts as unpaid!) + const resUnpaid = await store.order.list(googleAuthId, { onlyUnpaid: true }); + assert.equal(resUnpaid.total, 3, 'O-1004 (overpaid), O-1003 (unpaid), O-1002 (unpaid) are unpaid'); + assert.deepEqual(resUnpaid.orders.map((o) => o.number), ['O-1004', 'O-1003', 'O-1002']); + + // 5. onlyUndelivered + const resUndelivered = await store.order.list(googleAuthId, { onlyUndelivered: true }); + assert.equal(resUndelivered.total, 2, 'O-1001 and O-1003 are undelivered'); + assert.deepEqual(resUndelivered.orders.map((o) => o.number), ['O-1003', 'O-1001']); + + // 6. onlyUnpaid AND onlyUndelivered + const resBoth = await store.order.list(googleAuthId, { onlyUnpaid: true, onlyUndelivered: true }); + assert.equal(resBoth.total, 1, 'Only O-1003 is both unpaid and undelivered'); + assert.equal(resBoth.orders[0].number, 'O-1003'); + + // 7. seekMonths -1 (orders older than 1 month) + const resSeek = await store.order.list(googleAuthId, { seekMonths: -1 }); + assert.equal(resSeek.total, 1, 'Only O-1001 is older than 1 month'); + assert.equal(resSeek.orders[0].number, 'O-1001'); + + // 8. Paging + const resPaged = await store.order.list(googleAuthId, { offset: 0, limit: 1 }); + assert.equal(resPaged.total, 4); + assert.equal(resPaged.orders.length, 1); + assert.equal(resPaged.orders[0].number, 'O-1004'); + + const resPaged2 = await store.order.list(googleAuthId, { offset: 1, limit: 1 }); + assert.equal(resPaged2.total, 4); + assert.equal(resPaged2.orders.length, 1); + assert.equal(resPaged2.orders[0].number, 'O-1003'); + + // 9. Unpaged backwards-compatibility + const resAll = await store.order.list(googleAuthId); + assert(Array.isArray(resAll)); + assert.equal(resAll.length, 4); + + console.log('✓ All filter and pagination tests passed via store.order.list!'); + } finally { + try { + rmSync(tempDir, { recursive: true, force: true }); + } catch {} + } +} + +run().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/src/store/order/list.js b/src/store/order/list.js index 89a4f8e..766b58d 100644 --- a/src/store/order/list.js +++ b/src/store/order/list.js @@ -1,17 +1,13 @@ import { - COUNT_MANIFESTS as MSSQL_COUNT, GET_MANIFEST_LINES_BY_MANIFEST_IDS as MSSQL_LINES_BY_MANIFEST_IDS, - LIST_MANIFESTS as MSSQL_LIST, - LIST_MANIFESTS_PAGED as MSSQL_LIST_PAGED, ORDER_TYPE as MSSQL_ORDER_TYPE, } from '../../providers/mssql/queries/manifestDoc.js'; import { - COUNT_MANIFESTS as SQLITE_COUNT, GET_MANIFEST_LINES_BY_MANIFEST_IDS as SQLITE_LINES_BY_MANIFEST_IDS, - LIST_MANIFESTS as SQLITE_LIST, - LIST_MANIFESTS_PAGED as SQLITE_LIST_PAGED, ORDER_TYPE as SQLITE_ORDER_TYPE, } from '../../providers/sqlite3/queries/manifestDoc.js'; +import { GET_SHIPMENT_PREFIX as MSSQL_GET_SHIPMENT_PREFIX } from '../../providers/mssql/queries/shipment.js'; +import { GET_SHIPMENT_PREFIX as SQLITE_GET_SHIPMENT_PREFIX } from '../../providers/sqlite3/queries/shipment.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import { shapeSummary } from '../manifestDoc/helpers.js'; import { shapeLine } from '../manifestLines.js'; @@ -20,27 +16,31 @@ import makeRunner from '../runner.js'; export default function list(provider) { const access = resolveSelectedCompanyAccess(provider); const isSqlite = provider?.dialect === 'sqlite3'; - const sql = isSqlite ? SQLITE_LIST : MSSQL_LIST; - const sqlCount = isSqlite ? SQLITE_COUNT : MSSQL_COUNT; - const sqlPaged = isSqlite ? SQLITE_LIST_PAGED : MSSQL_LIST_PAGED; const sqlLinesByManifestIds = isSqlite ? SQLITE_LINES_BY_MANIFEST_IDS : MSSQL_LINES_BY_MANIFEST_IDS; + const sqlShipmentPrefix = isSqlite + ? SQLITE_GET_SHIPMENT_PREFIX + : MSSQL_GET_SHIPMENT_PREFIX; const orderType = isSqlite ? SQLITE_ORDER_TYPE : MSSQL_ORDER_TYPE; /** * Lists the orders of the user's selected company. * * @param {number} googleAuthId - The id of the Google auth user. - * @param {object} [opts] - Optional pagination options. + * @param {object} [opts] - Optional pagination and filter options. * @param {number} [opts.offset=0] - Number of orders to skip. - * @param {number} [opts.limit=20] - Number of orders to return. + * @param {number} [opts.limit=50] - Number of orders to return. + * @param {string} [opts.search] - Free-text search matching order number, external number, or customer name. + * @param {boolean} [opts.onlyUnpaid=false] - When true, returns only unpaid orders. + * @param {boolean} [opts.onlyUndelivered=false] - When true, returns only undelivered orders. + * @param {number} [opts.seekMonths] - Negative integer for cutoff months ago (e.g. -1). * @param {object} [tx] - Optional transaction. * @returns {Promise<{orders: Array<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, createdAt: string|null, lines: Array<{id: number, sku: string|null, name: string|null, pu: number, amount: number, net: number, rebate: number, taxrate: number, comment: string|null}>}>, total: number, offset: number, limit: number}|Array>} The orders. * * @example - * const result = await store.order.list(42, { offset: 0, limit: 20 }); - * // => { orders: [...], total: 100, offset: 0, limit: 20 } + * const result = await store.order.list(42, { offset: 0, limit: 50, search: '1002', onlyUnpaid: true, onlyUndelivered: true, seekMonths: -1 }); + * // => { orders: [...], total: 10, offset: 0, limit: 50 } * * const orders = await store.order.list(42); * // => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }] @@ -51,11 +51,20 @@ export default function list(provider) { let isPaged = false; let resolvedTx = tx; + const hasFilter = opts != null && typeof opts === 'object' && !opts._isTx && ( + opts.offset !== undefined || + opts.limit !== undefined || + (typeof opts.search === 'string' && opts.search.trim() !== '') || + opts.onlyUnpaid === true || + opts.onlyUndelivered === true || + opts.seekMonths !== undefined + ); + if (opts != null && typeof opts === 'object' && !opts._isTx) { - if (opts.offset !== undefined || opts.limit !== undefined) { + if (hasFilter || opts.offset !== undefined || opts.limit !== undefined) { isPaged = true; const parsedOffset = Number(opts.offset ?? 0); - const parsedLimit = Number(opts.limit ?? 20); + const parsedLimit = Number(opts.limit ?? 50); if (!Number.isInteger(parsedOffset) || parsedOffset < 0) { throw new Error('Invalid offset'); } @@ -72,18 +81,193 @@ export default function list(provider) { const runner = makeRunner(provider, resolvedTx); const { companyId } = await access(googleAuthId, runner); + const conditions = ['m.company_id = @companyId', `m.${isSqlite ? '"type"' : '[type]'} = @type`]; + const params = { + companyId, + type: orderType, + }; + + // Date cutoff via seekMonths (strictly integer) + if (opts?.seekMonths !== undefined) { + if (typeof opts.seekMonths !== 'number' || !Number.isInteger(opts.seekMonths)) { + throw new Error('Invalid seekMonths'); + } + const d = new Date(); + d.setMonth(d.getMonth() - Math.abs(opts.seekMonths)); + params.dateTo = d.toISOString(); + conditions.push(`m.${isSqlite ? '"date"' : '[date]'} <= @dateTo`); + } + + // Free-text search (strictly string) + if (typeof opts?.search === 'string' && opts.search.trim() !== '') { + params.searchPattern = `%${opts.search.trim()}%`; + if (isSqlite) { + conditions.push(`( + m."number" LIKE @searchPattern + OR m.external_number LIKE @searchPattern + OR e.name LIKE @searchPattern + OR e.first_name LIKE @searchPattern + OR (IFNULL(e.first_name, '') || ' ' || IFNULL(e.name, '')) LIKE @searchPattern + OR (IFNULL(e.name, '') || ' ' || IFNULL(e.first_name, '')) LIKE @searchPattern + )`); + } else { + conditions.push(`( + m.[number] LIKE @searchPattern + OR m.external_number LIKE @searchPattern + OR e.name LIKE @searchPattern + OR e.first_name LIKE @searchPattern + OR (ISNULL(e.first_name, '') + ' ' + ISNULL(e.name, '')) LIKE @searchPattern + OR (ISNULL(e.name, '') + ' ' + ISNULL(e.first_name, '')) LIKE @searchPattern + )`); + } + } + + // Only unpaid (strictly boolean true; overpaid orders also count as unpaid) + if (opts?.onlyUnpaid === true) { + conditions.push(`( + COALESCE(( + SELECT SUM(ma.amount * (ma.net * (1.0 - ma.rebate / 100.0)) * (1.0 + ma.taxrate / 100.0)) + FROM manifestarticle ma + WHERE ma.manifest_id = m.id + ), 0) = 0 + OR + ABS( + COALESCE(( + SELECT SUM(p.amount) + FROM payment p + WHERE p.manifest_id = m.id + ), 0) + - + COALESCE(( + SELECT SUM(ma.amount * (ma.net * (1.0 - ma.rebate / 100.0)) * (1.0 + ma.taxrate / 100.0)) + FROM manifestarticle ma + WHERE ma.manifest_id = m.id + ), 0) + ) >= 0.01 + )`); + } + + // Only undelivered (strictly boolean true) + if (opts?.onlyUndelivered === true) { + const prefixRes = await runner.query(sqlShipmentPrefix, { companyId }); + params.shipmentPrefix = prefixRes.rows[0]?.prefix?.trim?.() || '-L-'; + + if (isSqlite) { + conditions.push(`NOT ( + ( + COALESCE((SELECT SUM(ma.amount) FROM manifestarticle ma WHERE ma.manifest_id = m.id), 0) > 0 + AND + COALESCE(( + SELECT SUM(ma_s.amount) + FROM manifest m_s + JOIN manifestarticle ma_s ON ma_s.manifest_id = m_s.id + WHERE m_s.company_id = m.company_id + AND m_s."type" = 'shipment' + AND m_s."number" LIKE (m."number" || @shipmentPrefix || '%') + ), 0) >= (SELECT SUM(ma.amount) FROM manifestarticle ma WHERE ma.manifest_id = m.id) - 0.001 + ) + OR EXISTS ( + SELECT 1 FROM shipping s + WHERE ( + s.manifest_id = m.id + OR s.manifest_id IN ( + SELECT m_s.id FROM manifest m_s + WHERE m_s.company_id = m.company_id + AND m_s."type" = 'shipment' + AND m_s."number" LIKE (m."number" || @shipmentPrefix || '%') + ) + ) + AND LOWER(s."state") IN ('shipped', 'delivered') + ) + )`); + } else { + conditions.push(`NOT ( + ( + COALESCE((SELECT SUM(ma.amount) FROM manifestarticle ma WHERE ma.manifest_id = m.id), 0) > 0 + AND + COALESCE(( + SELECT SUM(ma_s.amount) + FROM manifest m_s + JOIN manifestarticle ma_s ON ma_s.manifest_id = m_s.id + WHERE m_s.company_id = m.company_id + AND m_s.[type] = 'shipment' + AND m_s.[number] LIKE (m.[number] + @shipmentPrefix + '%') + ), 0) >= (SELECT SUM(ma.amount) FROM manifestarticle ma WHERE ma.manifest_id = m.id) - 0.001 + ) + OR EXISTS ( + SELECT 1 FROM shipping s + WHERE ( + s.manifest_id = m.id + OR s.manifest_id IN ( + SELECT m_s.id FROM manifest m_s + WHERE m_s.company_id = m.company_id + AND m_s.[type] = 'shipment' + AND m_s.[number] LIKE (m.[number] + @shipmentPrefix + '%') + ) + ) + AND LOWER(s.[state]) IN ('shipped', 'delivered') + ) + )`); + } + } + + const whereClause = conditions.join('\n AND '); + const sqlCount = ` + SELECT COUNT(*) AS total + FROM manifest m + LEFT JOIN entity e ON e.id = m.entity_id + WHERE ${whereClause} + `; + + let sqlList; + if (isSqlite) { + sqlList = ` + SELECT + m.id, + m."number", + m."type", + m.entity_id AS entityId, + m.external_number AS externalNumber, + m."date", + m.created_at AS createdAt + FROM manifest m + LEFT JOIN entity e ON e.id = m.entity_id + WHERE ${whereClause} + ORDER BY m."date" DESC, m.id DESC + ${isPaged ? 'LIMIT @limit OFFSET @offset' : ''} + `; + } else { + sqlList = ` + SELECT + m.id, + m.[number], + m.[type], + m.entity_id AS entityId, + m.external_number AS externalNumber, + m.[date], + m.created_at AS createdAt + FROM manifest m + LEFT JOIN entity e ON e.id = m.entity_id + WHERE ${whereClause} + ORDER BY m.[date] DESC, m.id DESC + ${isPaged ? 'OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY' : ''} + `; + } + let manifestRows; let total = 0; if (isPaged) { + params.offset = offset; + params.limit = limit; const [countResult, listResult] = await Promise.all([ - runner.query(sqlCount, { companyId, type: orderType }), - runner.query(sqlPaged, { companyId, type: orderType, offset, limit }), + runner.query(sqlCount, params), + runner.query(sqlList, params), ]); total = Number(countResult.rows[0]?.total ?? 0); manifestRows = listResult.rows; } else { - const result = await runner.query(sql, { companyId, type: orderType }); + const result = await runner.query(sqlList, params); manifestRows = result.rows; total = manifestRows.length; } @@ -122,5 +306,3 @@ export default function list(provider) { return orders; }; } - -