feat: KKT fiscal/non-fiscal mode, multi-KKT per workstation, DTO port per device

- Migration 045: fiscal_mode + dto_port columns on workstation_devices
- Backend: pass fiscal_mode/dto_port to agent in test_device command
- Agent atol.ts: remove global DTO singleton, accept dtoPort per function call
- Agent test_device: returns real KKT info (model, serial, FN, shift status)
- Equipment page: fiscal/non-fiscal toggle + DTO port field when adding KKT
- Equipment page: show fiscal mode badge on device card, DTO port if non-default
- Equipment page: KKT test result shows model, serial, FN, shift status

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 14:06:44 +03:00
parent 2caf717131
commit f882cb2481
4 changed files with 87 additions and 8 deletions

View File

@@ -0,0 +1,4 @@
-- KKT fiscal mode and DTO port per device
ALTER TABLE workstation_devices
ADD COLUMN IF NOT EXISTS fiscal_mode BOOLEAN NOT NULL DEFAULT true,
ADD COLUMN IF NOT EXISTS dto_port INTEGER DEFAULT 16732;

View File

@@ -211,16 +211,18 @@ const workstationRoutes: FastifyPluginAsync = async (fastify) => {
fastify.post<WsParam & { Body: {
type: string; name: string; connection: string
network_host?: string; network_port?: number; com_port?: string; purpose?: string; config?: object
fiscal_mode?: boolean; dto_port?: number
} }>(
'/api/hotels/:slug/workstations/:id/devices',
{ onRequest: [fastify.authenticate] },
async (req, reply) => {
const { id } = req.params
const { type, name, connection, network_host, network_port, com_port, purpose, config } = req.body
const { type, name, connection, network_host, network_port, com_port, purpose, config, fiscal_mode, dto_port } = req.body
const { rows } = await db.query(
`INSERT INTO workstation_devices (workstation_id, type, name, connection, network_host, network_port, com_port, purpose, config)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) RETURNING *`,
[id, type, name, connection, network_host ?? null, network_port ?? null, com_port ?? null, purpose ?? 'other', config ?? {}],
`INSERT INTO workstation_devices (workstation_id, type, name, connection, network_host, network_port, com_port, purpose, config, fiscal_mode, dto_port)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) RETURNING *`,
[id, type, name, connection, network_host ?? null, network_port ?? null, com_port ?? null, purpose ?? 'other', config ?? {},
fiscal_mode ?? true, dto_port ?? 16732],
)
return reply.code(201).send(rows[0])
},
@@ -233,7 +235,7 @@ const workstationRoutes: FastifyPluginAsync = async (fastify) => {
async (req, reply) => {
const { deviceId } = req.params
const body = req.body as Record<string, unknown>
const fields = ['name', 'connection', 'network_host', 'network_port', 'com_port', 'purpose', 'config']
const fields = ['name', 'connection', 'network_host', 'network_port', 'com_port', 'purpose', 'config', 'fiscal_mode', 'dto_port']
const sets: string[] = []
const vals: unknown[] = []
fields.forEach(f => {
@@ -296,6 +298,8 @@ const workstationRoutes: FastifyPluginAsync = async (fastify) => {
network_host: device.network_host,
network_port: device.network_port,
com_port: device.com_port,
fiscal_mode: device.fiscal_mode,
dto_port: device.dto_port,
},
}) as { ok: boolean; error?: string; message?: string }
return result