u
This commit is contained in:
2
API.md
2
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}>}>`
|
- `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<void>`
|
- `delete(googleAuthId: number, id: number, tx?: object): Promise<void>`
|
||||||
- `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}>}>`
|
- `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, 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<object>>`
|
- `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, unfilteredTotal: number, offset: number, limit: number}|Array<object>>`
|
||||||
- `rebuildSummaries(provider: import('../../providers/provider.js').DatabaseProvider): void`
|
- `rebuildSummaries(provider: import('../../providers/provider.js').DatabaseProvider): void`
|
||||||
- `syncSummary(): void`
|
- `syncSummary(): void`
|
||||||
- `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}>}>`
|
- `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}>}>`
|
||||||
|
|||||||
@@ -115,13 +115,13 @@ Lists the orders of the user's selected company.
|
|||||||
|
|
||||||
**Returns**
|
**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<object>>` — The orders.
|
`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, unfilteredTotal: number, offset: number, limit: number}|Array<object>>` — The orders.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const result = await store.order.list(42, { offset: 0, limit: 50, search: '1002', onlyUnpaid: true, onlyUndelivered: true, seekMonths: -1 });
|
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 }
|
// => { orders: [...], total: 10, unfilteredTotal: 42, offset: 0, limit: 50 }
|
||||||
|
|
||||||
const orders = await store.order.list(42);
|
const orders = await store.order.list(42);
|
||||||
// => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }]
|
// => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }]
|
||||||
|
|||||||
@@ -143,46 +143,55 @@ async function run() {
|
|||||||
// 1. Search Alice
|
// 1. Search Alice
|
||||||
const resAlice = await store.order.list(googleAuthId, { search: 'Alice' });
|
const resAlice = await store.order.list(googleAuthId, { search: 'Alice' });
|
||||||
assert.equal(resAlice.total, 2, 'Should find 2 orders for Alice');
|
assert.equal(resAlice.total, 2, 'Should find 2 orders for Alice');
|
||||||
|
assert.equal(resAlice.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.deepEqual(resAlice.orders.map((o) => o.number), ['O-1003', 'O-1001']);
|
assert.deepEqual(resAlice.orders.map((o) => o.number), ['O-1003', 'O-1001']);
|
||||||
|
|
||||||
// 2. Search Bob
|
// 2. Search Bob
|
||||||
const resBob = await store.order.list(googleAuthId, { search: 'Bob' });
|
const resBob = await store.order.list(googleAuthId, { search: 'Bob' });
|
||||||
assert.equal(resBob.total, 2, 'Should find 2 orders for Bob');
|
assert.equal(resBob.total, 2, 'Should find 2 orders for Bob');
|
||||||
|
assert.equal(resBob.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.deepEqual(resBob.orders.map((o) => o.number), ['O-1004', 'O-1002']);
|
assert.deepEqual(resBob.orders.map((o) => o.number), ['O-1004', 'O-1002']);
|
||||||
|
|
||||||
// 3. Search 1002
|
// 3. Search 1002
|
||||||
const res1002 = await store.order.list(googleAuthId, { 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.total, 1, 'Should find 1 order for 1002');
|
||||||
|
assert.equal(res1002.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.equal(res1002.orders[0].number, 'O-1002');
|
assert.equal(res1002.orders[0].number, 'O-1002');
|
||||||
|
|
||||||
// 4. onlyUnpaid (O-1004 is overpaid, so it also counts as unpaid!)
|
// 4. onlyUnpaid (O-1004 is overpaid, so it also counts as unpaid!)
|
||||||
const resUnpaid = await store.order.list(googleAuthId, { onlyUnpaid: true });
|
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.equal(resUnpaid.total, 3, 'O-1004 (overpaid), O-1003 (unpaid), O-1002 (unpaid) are unpaid');
|
||||||
|
assert.equal(resUnpaid.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.deepEqual(resUnpaid.orders.map((o) => o.number), ['O-1004', 'O-1003', 'O-1002']);
|
assert.deepEqual(resUnpaid.orders.map((o) => o.number), ['O-1004', 'O-1003', 'O-1002']);
|
||||||
|
|
||||||
// 5. onlyUndelivered
|
// 5. onlyUndelivered
|
||||||
const resUndelivered = await store.order.list(googleAuthId, { onlyUndelivered: true });
|
const resUndelivered = await store.order.list(googleAuthId, { onlyUndelivered: true });
|
||||||
assert.equal(resUndelivered.total, 2, 'O-1001 and O-1003 are undelivered');
|
assert.equal(resUndelivered.total, 2, 'O-1001 and O-1003 are undelivered');
|
||||||
|
assert.equal(resUndelivered.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.deepEqual(resUndelivered.orders.map((o) => o.number), ['O-1003', 'O-1001']);
|
assert.deepEqual(resUndelivered.orders.map((o) => o.number), ['O-1003', 'O-1001']);
|
||||||
|
|
||||||
// 6. onlyUnpaid AND onlyUndelivered
|
// 6. onlyUnpaid AND onlyUndelivered
|
||||||
const resBoth = await store.order.list(googleAuthId, { onlyUnpaid: true, onlyUndelivered: true });
|
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.total, 1, 'Only O-1003 is both unpaid and undelivered');
|
||||||
|
assert.equal(resBoth.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.equal(resBoth.orders[0].number, 'O-1003');
|
assert.equal(resBoth.orders[0].number, 'O-1003');
|
||||||
|
|
||||||
// 7. seekMonths -1 (orders older than 1 month)
|
// 7. seekMonths -1 (orders older than 1 month)
|
||||||
const resSeek = await store.order.list(googleAuthId, { seekMonths: -1 });
|
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.total, 1, 'Only O-1001 is older than 1 month');
|
||||||
|
assert.equal(resSeek.unfilteredTotal, 4, 'Unfiltered total should be 4');
|
||||||
assert.equal(resSeek.orders[0].number, 'O-1001');
|
assert.equal(resSeek.orders[0].number, 'O-1001');
|
||||||
|
|
||||||
// 8. Paging
|
// 8. Paging
|
||||||
const resPaged = await store.order.list(googleAuthId, { offset: 0, limit: 1 });
|
const resPaged = await store.order.list(googleAuthId, { offset: 0, limit: 1 });
|
||||||
assert.equal(resPaged.total, 4);
|
assert.equal(resPaged.total, 4);
|
||||||
|
assert.equal(resPaged.unfilteredTotal, 4);
|
||||||
assert.equal(resPaged.orders.length, 1);
|
assert.equal(resPaged.orders.length, 1);
|
||||||
assert.equal(resPaged.orders[0].number, 'O-1004');
|
assert.equal(resPaged.orders[0].number, 'O-1004');
|
||||||
|
|
||||||
const resPaged2 = await store.order.list(googleAuthId, { offset: 1, limit: 1 });
|
const resPaged2 = await store.order.list(googleAuthId, { offset: 1, limit: 1 });
|
||||||
assert.equal(resPaged2.total, 4);
|
assert.equal(resPaged2.total, 4);
|
||||||
|
assert.equal(resPaged2.unfilteredTotal, 4);
|
||||||
assert.equal(resPaged2.orders.length, 1);
|
assert.equal(resPaged2.orders.length, 1);
|
||||||
assert.equal(resPaged2.orders[0].number, 'O-1003');
|
assert.equal(resPaged2.orders[0].number, 'O-1003');
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
|
COUNT_MANIFESTS as MSSQL_COUNT_MANIFESTS,
|
||||||
GET_MANIFEST_LINES_BY_MANIFEST_IDS as MSSQL_LINES_BY_MANIFEST_IDS,
|
GET_MANIFEST_LINES_BY_MANIFEST_IDS as MSSQL_LINES_BY_MANIFEST_IDS,
|
||||||
ORDER_TYPE as MSSQL_ORDER_TYPE,
|
ORDER_TYPE as MSSQL_ORDER_TYPE,
|
||||||
} from '../../providers/mssql/queries/manifestDoc.js';
|
} from '../../providers/mssql/queries/manifestDoc.js';
|
||||||
import {
|
import {
|
||||||
|
COUNT_MANIFESTS as SQLITE_COUNT_MANIFESTS,
|
||||||
GET_MANIFEST_LINES_BY_MANIFEST_IDS as SQLITE_LINES_BY_MANIFEST_IDS,
|
GET_MANIFEST_LINES_BY_MANIFEST_IDS as SQLITE_LINES_BY_MANIFEST_IDS,
|
||||||
ORDER_TYPE as SQLITE_ORDER_TYPE,
|
ORDER_TYPE as SQLITE_ORDER_TYPE,
|
||||||
} from '../../providers/sqlite3/queries/manifestDoc.js';
|
} from '../../providers/sqlite3/queries/manifestDoc.js';
|
||||||
@@ -23,6 +25,9 @@ export default function list(provider) {
|
|||||||
? SQLITE_GET_SHIPMENT_PREFIX
|
? SQLITE_GET_SHIPMENT_PREFIX
|
||||||
: MSSQL_GET_SHIPMENT_PREFIX;
|
: MSSQL_GET_SHIPMENT_PREFIX;
|
||||||
const orderType = isSqlite ? SQLITE_ORDER_TYPE : MSSQL_ORDER_TYPE;
|
const orderType = isSqlite ? SQLITE_ORDER_TYPE : MSSQL_ORDER_TYPE;
|
||||||
|
const sqlCountManifests = isSqlite
|
||||||
|
? SQLITE_COUNT_MANIFESTS
|
||||||
|
: MSSQL_COUNT_MANIFESTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists the orders of the user's selected company.
|
* Lists the orders of the user's selected company.
|
||||||
@@ -36,11 +41,11 @@ export default function list(provider) {
|
|||||||
* @param {boolean} [opts.onlyUndelivered=false] - When true, returns only undelivered 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 {number} [opts.seekMonths] - Negative integer for cutoff months ago (e.g. -1).
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @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<object>>} The orders.
|
* @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, unfilteredTotal: number, offset: number, limit: number}|Array<object>>} The orders.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const result = await store.order.list(42, { offset: 0, limit: 50, search: '1002', onlyUnpaid: true, onlyUndelivered: true, seekMonths: -1 });
|
* 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 }
|
* // => { orders: [...], total: 10, unfilteredTotal: 42, offset: 0, limit: 50 }
|
||||||
*
|
*
|
||||||
* const orders = await store.order.list(42);
|
* const orders = await store.order.list(42);
|
||||||
* // => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }]
|
* // => [{ id, number, type, entityId, externalNumber, date, createdAt, lines: [...] }]
|
||||||
@@ -194,22 +199,40 @@ export default function list(provider) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasUserFilters = (
|
||||||
|
opts?.seekMonths !== undefined ||
|
||||||
|
(typeof opts?.search === 'string' && opts.search.trim() !== '') ||
|
||||||
|
opts?.onlyUnpaid === true ||
|
||||||
|
opts?.onlyUndelivered === true
|
||||||
|
);
|
||||||
|
|
||||||
let manifestRows;
|
let manifestRows;
|
||||||
let total = 0;
|
let total = 0;
|
||||||
|
let unfilteredTotal = 0;
|
||||||
|
|
||||||
if (isPaged) {
|
if (isPaged) {
|
||||||
params.offset = offset;
|
params.offset = offset;
|
||||||
params.limit = limit;
|
params.limit = limit;
|
||||||
const [countResult, listResult] = await Promise.all([
|
const [countResult, listResult, unfilteredCountResult] = await Promise.all([
|
||||||
runner.query(sqlCount, params),
|
runner.query(sqlCount, params),
|
||||||
runner.query(sqlList, params),
|
runner.query(sqlList, params),
|
||||||
|
hasUserFilters ? runner.query(sqlCountManifests, { companyId, type: orderType }) : null,
|
||||||
]);
|
]);
|
||||||
total = Number(countResult.rows[0]?.total ?? 0);
|
total = Number(countResult.rows[0]?.total ?? 0);
|
||||||
|
unfilteredTotal = hasUserFilters
|
||||||
|
? Number(unfilteredCountResult?.rows[0]?.total ?? 0)
|
||||||
|
: total;
|
||||||
manifestRows = listResult.rows;
|
manifestRows = listResult.rows;
|
||||||
} else {
|
} else {
|
||||||
const result = await runner.query(sqlList, params);
|
const result = await runner.query(sqlList, params);
|
||||||
manifestRows = result.rows;
|
manifestRows = result.rows;
|
||||||
total = manifestRows.length;
|
total = manifestRows.length;
|
||||||
|
if (hasUserFilters) {
|
||||||
|
const countRes = await runner.query(sqlCountManifests, { companyId, type: orderType });
|
||||||
|
unfilteredTotal = Number(countRes.rows[0]?.total ?? 0);
|
||||||
|
} else {
|
||||||
|
unfilteredTotal = total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const manifestIds = manifestRows.map((r) => r.id);
|
const manifestIds = manifestRows.map((r) => r.id);
|
||||||
@@ -246,6 +269,7 @@ export default function list(provider) {
|
|||||||
return {
|
return {
|
||||||
orders,
|
orders,
|
||||||
total,
|
total,
|
||||||
|
unfilteredTotal,
|
||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user