This commit is contained in:
seb
2026-10-21 06:13:31 +02:00
parent ee0eb2820e
commit ada4d93f65
9 changed files with 286 additions and 1 deletions

View File

@@ -276,6 +276,8 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route
| [`routes/unit/upsert.md`](routes/unit/upsert.md) | `PUT /unit` |
| [`routes/v1/category.md`](routes/v1/category.md) | `GET /v1/category` |
| [`routes/pos/client.md`](routes/pos/client.md) | `GET /v1/client` |
| [`routes/v1/customer.md`](routes/v1/customer.md) | `GET /v1/customer` |
| [`routes/v1/customergroup.md`](routes/v1/customergroup.md) | `GET /v1/customergroup` |
| [`routes/pos/init.md`](routes/pos/init.md) | `GET /v1/init` |
| [`routes/pos/pimage.md`](routes/pos/pimage.md) | `GET /v1/pimage` |
| [`routes/v1/product.md`](routes/v1/product.md) | `GET /v1/product` |

View File

@@ -1,6 +1,6 @@
# Dash API Routes Overview (All)
Overview of all 264 API endpoints across all modules.
Overview of all 266 API endpoints across all modules.
### Notation
@@ -927,6 +927,12 @@ _none_
#### POS discovery and pairing — `GET /v1/client`
- Params: `query: authCode: str, name?: str`
- Returns: `200 { authCode: str|null, authToken: str|null, certificateFingerprint: str, certificateSerialNumber: str, mandantId: str, mandantName: str|null, mandantDatabase: str|null, serverFingerprint: str|null, name: str|null, serverTimestamp: str }`
#### JTL-POS customer catalog synchronization — `GET /v1/customer`
- Params: `query: lastChangedCustomer?: str, limit?: int`
- Returns: `200 { id: str, customerNumber: str, firstname: str, lastname: str, title: str, company: str, address: str, addressSupplement: str, city: str, postalCode: str, state: str, country: str, phone: str, email: str, customerGroupId: str, salutation: str, birthday: str, discount: str, taxIdNumber: str, lastChanged: str, debtorNumber: str }[]`
#### JTL-POS customer group synchronization — `GET /v1/customergroup`
- Params: `query: lastChangedCustomerGroup?: str, limit?: int`
- Returns: `200 { customerGroupId: str, name: str, standard: str, discountPercent: str, lastChanged: str }[]`
#### POS sync initialization counts — `GET /v1/init`
- Params: `query: lastChangedProduct?: int, lastChangedCategory?: int, lastChangedCustomer?: int, lastChangedCustomerGroup?: int, lastChangedCompositeProduct?: int, lastChangedDeletedEntity?: int`
- Returns: `200 { version: str, product_count: str, category_count: str, customer_count: str, customerGroup_count: str, compositeProduct_count: str, configurationGroup_count: str, configurationItem_count: str, deletedEntity_count: str, max_orderId_count: str }`

View File

@@ -0,0 +1,56 @@
# `GET /v1/customer`
Protected. Requires a valid session cookie (`credentials: 'include'`).
JTL-POS customer catalog synchronization
Returns customer list modified after lastChangedCustomer cursor for the authenticated POS register.
## Query parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `lastChangedCustomer` | no | string | Unix timestamp cursor of last customer sync |
| `limit` | no | integer | Maximum number of customers to return |
## Response `200`
Array of customer objects for JTL-POS
```json
[
{
"id": "…",
"customerNumber": "…",
"firstname": "…",
"lastname": "…",
"title": "…",
"company": "…",
"address": "…",
"addressSupplement": "…",
"city": "…",
"postalCode": "…",
"state": "…",
"country": "…",
"phone": "…",
"email": "…",
"customerGroupId": "…",
"salutation": "…",
"birthday": "…",
"discount": "…",
"taxIdNumber": "…",
"lastChanged": "…",
"debtorNumber": "…"
}
]
```
## Errors
| Status | Description |
|--------|-------------|
| 401 | Unauthorized |
---
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._

View File

@@ -0,0 +1,40 @@
# `GET /v1/customergroup`
Protected. Requires a valid session cookie (`credentials: 'include'`).
JTL-POS customer group synchronization
Returns customer groups modified after lastChangedCustomerGroup cursor for the authenticated POS register, excluding 'Lieferanten'.
## Query parameters
| Param | Required | Type | Description |
|-------|----------|------|-------------|
| `lastChangedCustomerGroup` | no | string | Unix timestamp cursor of last customer group sync |
| `limit` | no | integer | Maximum number of customer groups to return |
## Response `200`
Array of customer group objects for JTL-POS
```json
[
{
"customerGroupId": "1",
"name": "Endkunden",
"standard": "1",
"discountPercent": "0.000000",
"lastChanged": "1721000000"
}
]
```
## Errors
| Status | Description |
|--------|-------------|
| 401 | Unauthorized |
---
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._

View File

@@ -42,6 +42,8 @@ const OMITTED_ROUTES = new Set([
'GET /thumb/{fullHash}',
'GET /v1/category',
'GET /v1/client',
'GET /v1/customer',
'GET /v1/customergroup',
'GET /v1/init',
'GET /v1/pimage',
'GET /v1/product',

View File

@@ -70,11 +70,21 @@ export async function getCustomerCount(params) {
return store.posterminal.getCustomerCount(params);
}
export async function getCustomerList(params) {
const store = await getStore();
return store.posterminal.getCustomerList(params);
}
export async function getCustomerGroupCount(params) {
const store = await getStore();
return store.posterminal.getCustomerGroupCount(params);
}
export async function getCustomerGroupList(params) {
const store = await getStore();
return store.posterminal.getCustomerGroupList(params);
}
export async function getCompositeProductCount(params) {
const store = await getStore();
return store.posterminal.getCompositeProductCount(params);

View File

@@ -3,6 +3,8 @@ import { posAuthMiddleware } from './middleware/posAuth.js';
import { handleClient } from './routes/client.js';
import { handleInit } from './routes/init.js';
import { handleCategory } from './routes/category.js';
import { handleCustomerGroup } from './routes/customergroup.js';
import { handleCustomer } from './routes/customer.js';
import { handleProduct } from './routes/product.js';
import { handlePimage } from './routes/pimage.js';
@@ -16,6 +18,8 @@ router.get('/init', posAuthMiddleware, handleInit);
// POS master data synchronization
router.get('/category', posAuthMiddleware, handleCategory);
router.get('/customergroup', posAuthMiddleware, handleCustomerGroup);
router.get('/customer', posAuthMiddleware, handleCustomer);
router.get('/product', posAuthMiddleware, handleProduct);
// POS image delivery

96
src/v1/routes/customer.js Normal file
View File

@@ -0,0 +1,96 @@
import { getCustomerList } from '../../db/posterminal.js';
/**
* @openapi
* /v1/customer:
* get:
* summary: JTL-POS customer catalog synchronization
* description: Returns customer list modified after lastChangedCustomer cursor for the authenticated POS register.
* tags:
* - POS Sync
* security:
* - BearerAuth: []
* parameters:
* - in: query
* name: lastChangedCustomer
* schema:
* type: string
* description: Unix timestamp cursor of last customer sync
* - in: query
* name: limit
* schema:
* type: integer
* default: 20
* description: Maximum number of customers to return
* responses:
* 200:
* description: Array of customer objects for JTL-POS
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* properties:
* id:
* type: string
* customerNumber:
* type: string
* firstname:
* type: string
* lastname:
* type: string
* title:
* type: string
* company:
* type: string
* address:
* type: string
* addressSupplement:
* type: string
* city:
* type: string
* postalCode:
* type: string
* state:
* type: string
* country:
* type: string
* phone:
* type: string
* email:
* type: string
* customerGroupId:
* type: string
* salutation:
* type: string
* birthday:
* type: string
* discount:
* type: string
* taxIdNumber:
* type: string
* lastChanged:
* type: string
* debtorNumber:
* type: string
* 401:
* description: Unauthorized
*/
export async function handleCustomer(req, res, next) {
try {
const posterminal = req.posterminal;
const cursor = Number(req.query.lastChangedCustomer) || 0;
const limit = Number(req.query.limit) || 20;
const customers = await getCustomerList({
posterminalId: posterminal.id,
cursor,
limit,
});
res.json(customers);
} catch (err) {
next(err);
}
}

View File

@@ -0,0 +1,69 @@
import { getCustomerGroupList } from '../../db/posterminal.js';
/**
* @openapi
* /v1/customergroup:
* get:
* summary: JTL-POS customer group synchronization
* description: Returns customer groups modified after lastChangedCustomerGroup cursor for the authenticated POS register, excluding 'Lieferanten'.
* tags:
* - POS Sync
* security:
* - BearerAuth: []
* parameters:
* - in: query
* name: lastChangedCustomerGroup
* schema:
* type: string
* description: Unix timestamp cursor of last customer group sync
* - in: query
* name: limit
* schema:
* type: integer
* default: 50
* description: Maximum number of customer groups to return
* responses:
* 200:
* description: Array of customer group objects for JTL-POS
* content:
* application/json:
* schema:
* type: array
* items:
* type: object
* properties:
* customerGroupId:
* type: string
* example: "1"
* name:
* type: string
* example: "Endkunden"
* standard:
* type: string
* example: "1"
* discountPercent:
* type: string
* example: "0.000000"
* lastChanged:
* type: string
* example: "1721000000"
* 401:
* description: Unauthorized
*/
export async function handleCustomerGroup(req, res, next) {
try {
const posterminal = req.posterminal;
const cursor = Number(req.query.lastChangedCustomerGroup) || 0;
const limit = Number(req.query.limit) || 50;
const customerGroups = await getCustomerGroupList({
posterminalId: posterminal.id,
cursor,
limit,
});
res.json(customerGroups);
} catch (err) {
next(err);
}
}