This commit is contained in:
seb
2026-10-08 01:37:30 +02:00
parent 9ba86c4216
commit cd396363bd
9 changed files with 367 additions and 121 deletions

View File

@@ -1172,6 +1172,26 @@
* pairingpin:
* type: string
* nullable: true
* token:
* type: string
* nullable: true
* pairedAt:
* type: string
* nullable: true
* clientserial:
* type: string
* nullable: true
* rootCategoryId:
* type: integer
* nullable: true
* syncRootArticles:
* type: boolean
* lastseenAt:
* type: string
* nullable: true
* updatedAt:
* type: string
* nullable: true
* categoryIds:
* type: array
* items:

View File

@@ -118,6 +118,12 @@ export function register(app, basePath = '') {
* properties:
* name:
* type: string
* rootCategoryId:
* type: integer
* nullable: true
* syncRootArticles:
* type: boolean
* default: true
* example:
* name: "Kassa 1"
* responses:
@@ -168,11 +174,19 @@ export function register(app, basePath = '') {
}
const pairingpin = String(randomInt(100000, 999999));
const rootCategoryId = req.body.rootCategoryId !== undefined
? req.body.rootCategoryId
: req.body.root_category_id;
const syncRootArticles = req.body.syncRootArticles !== undefined
? req.body.syncRootArticles
: req.body.sync_root_articles;
try {
const posterminal = await db.upsert(req.user.id, {
name: name.trim(),
pairingpin,
rootCategoryId,
syncRootArticles,
});
res.status(200).json({ posterminal });
} catch (error) {
@@ -182,6 +196,122 @@ export function register(app, basePath = '') {
}
});
/**
* @openapi
* /posterminal/{id}:
* patch:
* tags: [Posterminal]
* summary: Update POS terminal
* description: Updates a POS terminal configuration (name, root category, sync settings, or pairing pin).
* security:
* - cookieAuth: []
* x-markdown: posterminal/update.md
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* description: POS terminal ID
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* name:
* type: string
* rootCategoryId:
* type: integer
* nullable: true
* syncRootArticles:
* type: boolean
* pairingpin:
* type: string
* nullable: true
* example:
* name: "Kassa 1 Neu"
* rootCategoryId: 10
* syncRootArticles: false
* responses:
* 200:
* description: Updated posterminal
* content:
* application/json:
* schema:
* type: object
* properties:
* posterminal:
* $ref: '#/components/schemas/Posterminal'
* 400:
* description: Invalid posterminal or no company selected
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 401:
* description: Unauthorized
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 403:
* description: Not authorized
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* 404:
* description: Posterminal not found
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
*/
app.patch(`${basePath}/posterminal/:id`, async (req, res) => {
const selected = requireSelectedCompany(req);
if (selected.error) {
return res.status(400).json({ error: selected.error });
}
const parsed = parsePositiveInt(req.params.id, 'id');
if (parsed.error) {
return res.status(400).json({ error: parsed.error });
}
const payload = { id: parsed.id };
if (req.body.name !== undefined) {
if (typeof req.body.name !== 'string' || !req.body.name.trim()) {
return res.status(400).json({ error: 'name must be a non-empty string' });
}
payload.name = req.body.name.trim();
}
if (req.body.rootCategoryId !== undefined || req.body.root_category_id !== undefined) {
const rawCat = req.body.rootCategoryId !== undefined ? req.body.rootCategoryId : req.body.root_category_id;
payload.rootCategoryId = rawCat != null ? Number(rawCat) : null;
}
if (req.body.syncRootArticles !== undefined || req.body.sync_root_articles !== undefined) {
const rawSync = req.body.syncRootArticles !== undefined ? req.body.syncRootArticles : req.body.sync_root_articles;
payload.syncRootArticles = Boolean(rawSync);
}
if (req.body.pairingpin !== undefined) {
payload.pairingpin = req.body.pairingpin ? String(req.body.pairingpin).trim() : null;
}
try {
const posterminal = await db.upsert(req.user.id, payload);
res.status(200).json({ posterminal });
} catch (error) {
const status = posterminalErrorStatus(error);
if (status === 500) console.error('Update posterminal failed:', error);
res.status(status).json({ error: error.message });
}
});
/**
* @openapi
* /posterminal/{id}:

View File

@@ -45,6 +45,11 @@ export async function findByToken(token) {
return store.posterminal.findByToken(token);
}
export async function touchLastseen(id) {
const store = await getStore();
return store.posterminal.touchLastseen(id);
}
export async function pair(id, data) {
const store = await getStore();
return store.posterminal.pair(id, data);

View File

@@ -58,6 +58,9 @@ export async function posAuthMiddleware(req, res, next) {
}
req.posterminal = terminal;
db.touchLastseen(terminal.id).catch((err) => {
console.error('Failed to touch lastseen for posterminal:', err);
});
next();
} catch (err) {
console.error('POS auth error:', err);