This commit is contained in:
seb
2026-10-21 06:13:29 +02:00
parent b0014d6629
commit e085bcaeba
7 changed files with 301 additions and 1 deletions

2
API.md
View File

@@ -261,6 +261,8 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
- `getCompositeProductCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise<number>`
- `getCustomerCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise<number>`
- `getCustomerGroupCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise<number>`
- `getCustomerGroupList(input: {posterminalId: number, cursor?: number, limit?: number}, tx?: object): Promise<Array<{customerGroupId: string, name: string, standard: string, discountPercent: string, lastChanged: string}>>`
- `getCustomerList(input: {posterminalId: number, cursor?: number, limit?: number}, tx?: object): Promise<Array<object>>`
- `getDeletedEntityCount(input?: {posterminalId?: number, cursor?: number}): Promise<number>`
- `getMaxOrderIdCount(input: {posterminalId: number}, tx?: object): Promise<number>`
- `getProductCount(input: {posterminalId: number, cursor?: number}, tx?: object): Promise<number>`

View File

@@ -160,6 +160,46 @@ Counts customer groups of the POS terminal company updated after the given unix
`Promise<number>` — The count of changed records.
## `posterminal.getCustomerGroupList`
*Source: `src/store/posterminal/getCustomerGroupList.js`*
Lists customer groups for a POS terminal modified after the cursor, excluding 'Lieferanten'.
**Parameters**
| Name | Type | Description |
| --- | --- | --- |
| `input` | `object` | |
| `input.posterminalId` | `number` | The POS terminal id. |
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
| `[input.limit=50]` | `number` | Max items to return. |
| `[tx]` | `object` | Optional transaction. |
**Returns**
`Promise<Array<{customerGroupId: string, name: string, standard: string, discountPercent: string, lastChanged: string}>>`
## `posterminal.getCustomerList`
*Source: `src/store/posterminal/getCustomerList.js`*
Lists customers for a POS terminal modified after the cursor, excluding 'Lieferanten'.
**Parameters**
| Name | Type | Description |
| --- | --- | --- |
| `input` | `object` | |
| `input.posterminalId` | `number` | The POS terminal id. |
| `[input.cursor=0]` | `number` | Unix timestamp cursor. |
| `[input.limit=20]` | `number` | Max items to return. |
| `[tx]` | `object` | Optional transaction. |
**Returns**
`Promise<Array<object>>`
## `posterminal.getDeletedEntityCount`
*Source: `src/store/posterminal/getDeletedEntityCount.js`*

View File

@@ -121,7 +121,9 @@ import posterminalPair from './store/posterminal/pair.js';
import posterminalGetProductCount from './store/posterminal/getProductCount.js';
import posterminalGetCategoryCount from './store/posterminal/getCategoryCount.js';
import posterminalGetCustomerCount from './store/posterminal/getCustomerCount.js';
import posterminalGetCustomerList from './store/posterminal/getCustomerList.js';
import posterminalGetCustomerGroupCount from './store/posterminal/getCustomerGroupCount.js';
import posterminalGetCustomerGroupList from './store/posterminal/getCustomerGroupList.js';
import posterminalGetCompositeProductCount from './store/posterminal/getCompositeProductCount.js';
import posterminalGetDeletedEntityCount from './store/posterminal/getDeletedEntityCount.js';
import posterminalGetMaxOrderIdCount from './store/posterminal/getMaxOrderIdCount.js';
@@ -481,7 +483,9 @@ export default class LibDashStore {
getProductCount: posterminalGetProductCount(provider),
getCategoryCount: posterminalGetCategoryCount(provider),
getCustomerCount: posterminalGetCustomerCount(provider),
getCustomerList: posterminalGetCustomerList(provider),
getCustomerGroupCount: posterminalGetCustomerGroupCount(provider),
getCustomerGroupList: posterminalGetCustomerGroupList(provider),
getCompositeProductCount: posterminalGetCompositeProductCount(provider),
getDeletedEntityCount: posterminalGetDeletedEntityCount(provider),
getMaxOrderIdCount: posterminalGetMaxOrderIdCount(provider),

View File

@@ -189,10 +189,11 @@ SELECT COUNT(*) AS count
FROM entity e
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
WHERE cg.name NOT IN ('Lieferanten', 'POS')
WHERE cg.name <> 'Lieferanten'
AND DATEDIFF_BIG(second, '1970-01-01', e.updated_at) > @cursor
`;
export const COUNT_CUSTOMER_GROUPS = `
SELECT COUNT(*) AS count
FROM customergroup cg
@@ -387,6 +388,80 @@ WHERE pc.posterminal_id = @posterminalId
ORDER BY ca.article_id ASC, ca.category_id ASC
`;
export const LIST_POS_CUSTOMER_GROUPS = `
SELECT TOP (@limit)
cg.id,
cg.name,
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
'0.000000' AS discountPercent,
DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) AS lastChanged
FROM customergroup cg
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
INNER JOIN company co ON co.id = pt.company_id
WHERE cg.name <> 'Lieferanten'
AND DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) > @cursor
ORDER BY DATEDIFF_BIG(second, '1970-01-01', cg.updated_at) ASC, cg.id ASC
`;
export const LIST_POS_CUSTOMERS = `
SELECT TOP (@limit)
e.id,
e.customergroup_id AS customergroupId,
e.first_name AS firstName,
e.name AS lastName,
e.[number] AS customerNumber,
(
SELECT TOP 1 ea.street
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
) AS street,
(
SELECT TOP 1 ea.streetnumber
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
) AS streetNumber,
(
SELECT TOP 1 ea.city
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
) AS city,
(
SELECT TOP 1 ea.zip
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
) AS postalCode,
(
SELECT TOP 1 ea.county
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
) AS [state],
(
SELECT TOP 1 ec.contact
FROM entitycontact ec
WHERE ec.entity_id = e.id AND ec.contacttype IN ('phone', 'mobile', 'tel')
ORDER BY ec.sort ASC, ec.id ASC
) AS phone,
(
SELECT TOP 1 ec.contact
FROM entitycontact ec
WHERE ec.entity_id = e.id AND ec.contacttype IN ('email', 'mail')
ORDER BY ec.sort ASC, ec.id ASC
) AS email,
DATEDIFF_BIG(second, '1970-01-01', e.updated_at) AS lastChanged
FROM entity e
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
WHERE cg.name <> 'Lieferanten'
AND DATEDIFF_BIG(second, '1970-01-01', e.updated_at) > @cursor
ORDER BY DATEDIFF_BIG(second, '1970-01-01', e.updated_at) ASC, e.id ASC
`;
export const LIST_POS_CUSTOMER_GROUP_IDS = `
SELECT cg.id
FROM customergroup cg
@@ -395,6 +470,7 @@ WHERE cg.name <> 'Lieferanten'
ORDER BY cg.id ASC
`;
export const LIST_POS_PRODUCT_PRICES = `
SELECT
pr.article_id AS articleId,

View File

@@ -29,6 +29,88 @@ SELECT @posterminalId, id FROM cats WHERE 1
ON CONFLICT (posterminal_id, category_id) DO NOTHING
`;
export const LIST_POS_CUSTOMER_GROUPS = `
SELECT
cg.id,
cg.name,
CASE WHEN cg.id = co.poscustomergroup_id THEN '1' ELSE '0' END AS standard,
'0.000000' AS discountPercent,
CAST(strftime('%s', cg.updated_at) AS INTEGER) AS lastChanged
FROM customergroup cg
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
INNER JOIN company co ON co.id = pt.company_id
WHERE cg.name <> 'Lieferanten'
AND CAST(strftime('%s', cg.updated_at) AS INTEGER) > @cursor
ORDER BY lastChanged ASC, cg.id ASC
LIMIT @limit
`;
export const LIST_POS_CUSTOMERS = `
SELECT
e.id,
e.customergroup_id AS customergroupId,
e.first_name AS firstName,
e.name AS lastName,
e."number" AS customerNumber,
(
SELECT ea.street
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
LIMIT 1
) AS street,
(
SELECT ea.streetnumber
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
LIMIT 1
) AS streetNumber,
(
SELECT ea.city
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
LIMIT 1
) AS city,
(
SELECT ea.zip
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
LIMIT 1
) AS postalCode,
(
SELECT ea.county
FROM entityaddress ea
WHERE ea.entity_id = e.id
ORDER BY CASE WHEN ea.addresstype = 'billing' THEN 0 ELSE 1 END, ea.sort ASC, ea.id ASC
LIMIT 1
) AS "state",
(
SELECT ec.contact
FROM entitycontact ec
WHERE ec.entity_id = e.id AND ec.contacttype IN ('phone', 'mobile', 'tel')
ORDER BY ec.sort ASC, ec.id ASC
LIMIT 1
) AS phone,
(
SELECT ec.contact
FROM entitycontact ec
WHERE ec.entity_id = e.id AND ec.contacttype IN ('email', 'mail')
ORDER BY ec.sort ASC, ec.id ASC
LIMIT 1
) AS email,
CAST(strftime('%s', e.updated_at) AS INTEGER) AS lastChanged
FROM entity e
INNER JOIN customergroup cg ON cg.id = e.customergroup_id
INNER JOIN posterminal pt ON pt.id = @posterminalId AND pt.company_id = cg.company_id
WHERE cg.name <> 'Lieferanten'
AND CAST(strftime('%s', e.updated_at) AS INTEGER) > @cursor
ORDER BY lastChanged ASC, e.id ASC
LIMIT @limit
`;
export const LIST_POS_CATEGORIES = `
SELECT
c.id,

View File

@@ -0,0 +1,40 @@
import { LIST_POS_CUSTOMER_GROUPS as MSSQL_SQL } from '../../providers/mssql/queries/posterminal.js';
import { LIST_POS_CUSTOMER_GROUPS as SQLITE_SQL } from '../../providers/sqlite3/queries/posterminal.js';
import makeRunner from '../runner.js';
function normalizeCursor(cursor) {
const n = Number(cursor) || 0;
if (n <= 0) return 0;
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
}
export default function getCustomerGroupList(provider) {
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
/**
* Lists customer groups for a POS terminal modified after the cursor, excluding 'Lieferanten'.
*
* @param {object} input
* @param {number} input.posterminalId - The POS terminal id.
* @param {number} [input.cursor=0] - Unix timestamp cursor.
* @param {number} [input.limit=50] - Max items to return.
* @param {object} [tx] - Optional transaction.
* @returns {Promise<Array<{customerGroupId: string, name: string, standard: string, discountPercent: string, lastChanged: string}>>}
*/
return async ({ posterminalId, cursor = 0, limit = 50 } = {}, tx) => {
const safeLimit = Number.isInteger(limit) && limit > 0 ? limit : 50;
const result = await makeRunner(provider, tx).query(sql, {
posterminalId: Number(posterminalId),
cursor: normalizeCursor(cursor),
limit: safeLimit,
});
return result.rows.map((row) => ({
customerGroupId: String(row.id),
name: String(row.name ?? ''),
standard: String(row.standard ?? '0'),
discountPercent: String(row.discountPercent ?? '0.000000'),
lastChanged: String(row.lastChanged),
}));
};
}

View File

@@ -0,0 +1,56 @@
import { LIST_POS_CUSTOMERS as MSSQL_SQL } from '../../providers/mssql/queries/posterminal.js';
import { LIST_POS_CUSTOMERS as SQLITE_SQL } from '../../providers/sqlite3/queries/posterminal.js';
import makeRunner from '../runner.js';
function normalizeCursor(cursor) {
const n = Number(cursor) || 0;
if (n <= 0) return 0;
return n >= 1e11 ? Math.floor(n / 1000) : Math.floor(n);
}
export default function getCustomerList(provider) {
const sql = provider?.dialect === 'sqlite3' ? SQLITE_SQL : MSSQL_SQL;
/**
* Lists customers for a POS terminal modified after the cursor, excluding 'Lieferanten'.
*
* @param {object} input
* @param {number} input.posterminalId - The POS terminal id.
* @param {number} [input.cursor=0] - Unix timestamp cursor.
* @param {number} [input.limit=20] - Max items to return.
* @param {object} [tx] - Optional transaction.
* @returns {Promise<Array<object>>}
*/
return async ({ posterminalId, cursor = 0, limit = 20 } = {}, tx) => {
const safeLimit = Number.isInteger(limit) && limit > 0 ? limit : 20;
const result = await makeRunner(provider, tx).query(sql, {
posterminalId: Number(posterminalId),
cursor: normalizeCursor(cursor),
limit: safeLimit,
});
return result.rows.map((row) => ({
id: String(row.id),
customerNumber: String(row.customerNumber ?? ''),
firstname: String(row.firstName ?? ''),
lastname: String(row.lastName ?? ''),
title: '',
company: '',
address: [row.street, row.streetNumber].filter(Boolean).join(' '),
addressSupplement: '',
city: String(row.city ?? ''),
postalCode: String(row.postalCode ?? ''),
state: String(row.state ?? ''),
country: 'DE',
phone: String(row.phone ?? ''),
email: String(row.email ?? ''),
customerGroupId: String(row.customergroupId ?? '1'),
salutation: '',
birthday: '',
discount: '0.00',
taxIdNumber: '',
lastChanged: String(row.lastChanged),
debtorNumber: '0',
}));
};
}