u
This commit is contained in:
@@ -1693,6 +1693,18 @@
|
||||
* nullable: true
|
||||
* syncRootArticles:
|
||||
* type: boolean
|
||||
* sort:
|
||||
* type: integer
|
||||
* description: Display order (ascending)
|
||||
* default: 0
|
||||
* enabled:
|
||||
* type: boolean
|
||||
* description: Whether terminal is active/allowed to sync
|
||||
* default: true
|
||||
* clientversion:
|
||||
* type: string
|
||||
* nullable: true
|
||||
* description: Client software version reported by POS terminal
|
||||
* lastseenAt:
|
||||
* type: string
|
||||
* nullable: true
|
||||
|
||||
@@ -132,6 +132,12 @@ export function register(app, basePath = '') {
|
||||
* syncRootArticles:
|
||||
* type: boolean
|
||||
* default: true
|
||||
* sort:
|
||||
* type: integer
|
||||
* default: 0
|
||||
* enabled:
|
||||
* type: boolean
|
||||
* default: true
|
||||
* example:
|
||||
* name: "Kassa 1"
|
||||
* responses:
|
||||
@@ -190,6 +196,11 @@ export function register(app, basePath = '') {
|
||||
const syncRootArticles = req.body.syncRootArticles !== undefined
|
||||
? req.body.syncRootArticles
|
||||
: req.body.sync_root_articles;
|
||||
const sort = req.body.sort !== undefined ? Number(req.body.sort) : undefined;
|
||||
if (sort !== undefined && !Number.isInteger(sort)) {
|
||||
return res.status(400).json({ error: 'sort must be an integer' });
|
||||
}
|
||||
const enabled = req.body.enabled !== undefined ? Boolean(req.body.enabled) : undefined;
|
||||
|
||||
try {
|
||||
const posterminal = await db.upsert(req.user.id, {
|
||||
@@ -197,6 +208,8 @@ export function register(app, basePath = '') {
|
||||
pairingpin,
|
||||
rootCategoryId,
|
||||
syncRootArticles,
|
||||
sort,
|
||||
enabled,
|
||||
});
|
||||
res.status(200).json({ posterminal });
|
||||
} catch (error) {
|
||||
@@ -239,6 +252,13 @@ export function register(app, basePath = '') {
|
||||
* nullable: true
|
||||
* syncRootArticles:
|
||||
* type: boolean
|
||||
* sort:
|
||||
* type: integer
|
||||
* enabled:
|
||||
* type: boolean
|
||||
* clientversion:
|
||||
* type: string
|
||||
* nullable: true
|
||||
* pairingpin:
|
||||
* type: string
|
||||
* nullable: true
|
||||
@@ -312,6 +332,22 @@ export function register(app, basePath = '') {
|
||||
payload.syncRootArticles = Boolean(rawSync);
|
||||
}
|
||||
|
||||
if (req.body.sort !== undefined) {
|
||||
const rawSort = Number(req.body.sort);
|
||||
if (!Number.isInteger(rawSort)) {
|
||||
return res.status(400).json({ error: 'sort must be an integer' });
|
||||
}
|
||||
payload.sort = rawSort;
|
||||
}
|
||||
|
||||
if (req.body.enabled !== undefined) {
|
||||
payload.enabled = Boolean(req.body.enabled);
|
||||
}
|
||||
|
||||
if (req.body.clientversion !== undefined) {
|
||||
payload.clientversion = req.body.clientversion ? String(req.body.clientversion).trim() : null;
|
||||
}
|
||||
|
||||
if (req.body.pairingpin !== undefined) {
|
||||
payload.pairingpin = req.body.pairingpin ? String(req.body.pairingpin).trim() : null;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ export async function touchLastseen(id) {
|
||||
return store.posterminal.touchLastseen(id);
|
||||
}
|
||||
|
||||
export async function setClientversion(id, clientversion) {
|
||||
const store = await getStore();
|
||||
return store.posterminal.setClientversion(id, clientversion);
|
||||
}
|
||||
|
||||
export async function pair(id, data) {
|
||||
const store = await getStore();
|
||||
return store.posterminal.pair(id, data);
|
||||
|
||||
41
src/db/provider.js
Normal file
41
src/db/provider.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { MssqlProvider } from 'libdashstore/providers/mssql';
|
||||
import { BetterSqlite3Provider } from 'libdashstore/providers/better-sqlite3';
|
||||
import env from '../config/env.js';
|
||||
|
||||
function getMssqlConfig() {
|
||||
const { server, database, user, password, port, encrypt, trustServerCertificate } = env.mssql;
|
||||
|
||||
if (!server || !database || !user || !password) {
|
||||
throw new Error('MSSQL is not configured (MSSQL_SERVER, MSSQL_DATABASE, MSSQL_USER, MSSQL_PASSWORD required)');
|
||||
}
|
||||
|
||||
return {
|
||||
server,
|
||||
database,
|
||||
user,
|
||||
password,
|
||||
port,
|
||||
storageDir: env.storageDir,
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 0,
|
||||
idleTimeoutMillis: 30_000,
|
||||
},
|
||||
options: {
|
||||
encrypt,
|
||||
trustServerCertificate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the configured (uninitialized) libdashstore provider from `.env`.
|
||||
* @returns {MssqlProvider | BetterSqlite3Provider}
|
||||
*/
|
||||
export function createProvider() {
|
||||
if (env.dbProvider === 'sqlite' || env.dbProvider === 'better-sqlite3') {
|
||||
return new BetterSqlite3Provider(env.sqlite);
|
||||
}
|
||||
return new MssqlProvider(getMssqlConfig(), { storageDir: env.storageDir });
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import LibDashStore from 'libdashstore';
|
||||
import { MssqlProvider } from 'libdashstore/providers/mssql';
|
||||
import { BetterSqlite3Provider } from 'libdashstore/providers/better-sqlite3';
|
||||
import env from '../config/env.js';
|
||||
import { createProvider } from './provider.js';
|
||||
import { createLogger, chalk } from '../util/logger.js';
|
||||
import { clearCachedCompanyUsers, clearCachedUser } from '../api/middleware/auth.js';
|
||||
import { clearDeletedCompany, setUserCompany } from '../api/sse.js';
|
||||
@@ -134,34 +132,10 @@ function wrapStoreWithTiming(rawStore) {
|
||||
return rawStore;
|
||||
}
|
||||
|
||||
function getMssqlConfig() {
|
||||
const { server, database, user, password, port, encrypt, trustServerCertificate } = env.mssql;
|
||||
|
||||
if (!server || !database || !user || !password) {
|
||||
throw new Error('MSSQL is not configured (MSSQL_SERVER, MSSQL_DATABASE, MSSQL_USER, MSSQL_PASSWORD required)');
|
||||
}
|
||||
|
||||
return {
|
||||
server,
|
||||
database,
|
||||
user,
|
||||
password,
|
||||
port,
|
||||
storageDir: env.storageDir,
|
||||
pool: {
|
||||
max: 10,
|
||||
min: 0,
|
||||
idleTimeoutMillis: 30_000,
|
||||
},
|
||||
options: {
|
||||
encrypt,
|
||||
trustServerCertificate,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialized LibDashStore singleton.
|
||||
* `provider.initialize()` applies pending schema upgrades (libdashstore
|
||||
* `src/providers/<provider>/upgrade/`) before the store is used.
|
||||
* @returns {Promise<InstanceType<typeof LibDashStore>>}
|
||||
*/
|
||||
export async function getStore() {
|
||||
@@ -171,11 +145,7 @@ export async function getStore() {
|
||||
|
||||
if (!connecting) {
|
||||
connecting = (async () => {
|
||||
if (env.dbProvider === 'sqlite' || env.dbProvider === 'better-sqlite3') {
|
||||
provider = new BetterSqlite3Provider(env.sqlite);
|
||||
} else {
|
||||
provider = new MssqlProvider(getMssqlConfig(), { storageDir: env.storageDir });
|
||||
}
|
||||
provider = createProvider();
|
||||
await provider.initialize();
|
||||
store = wrapStoreWithTiming(await new LibDashStore(provider));
|
||||
return store;
|
||||
|
||||
@@ -57,6 +57,11 @@ export async function posAuthMiddleware(req, res, next) {
|
||||
return res.status(401).json({ Message: 'Authorization has been denied for this request.' });
|
||||
}
|
||||
|
||||
if (terminal.enabled === 0 || terminal.enabled === false) {
|
||||
console.log(chalk.yellow(` [posAuth] Terminal "${terminal.id}" is disabled`));
|
||||
return res.status(403).json({ Message: 'Authorization has been denied for this request.' });
|
||||
}
|
||||
|
||||
req.posterminal = terminal;
|
||||
db.touchLastseen(terminal.id).catch((err) => {
|
||||
console.error('Failed to touch lastseen for posterminal:', err);
|
||||
|
||||
@@ -83,6 +83,13 @@ export function buildClientStep2(authCode, config) {
|
||||
* type: string
|
||||
* description: Client device name or serial identifier (default 'JTL-POS')
|
||||
* example: "Kasse 1"
|
||||
* - in: query
|
||||
* name: clientversion
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Optional client app version (for future POS clients during pairing)
|
||||
* example: "1.10.12.0"
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Discovery or pairing successful
|
||||
@@ -160,11 +167,13 @@ export async function handleClient(req, res) {
|
||||
const token = terminal.token;
|
||||
const strToken = String(token || crypto.randomBytes(16).toString('hex')).trim();
|
||||
const pairedAt = serverTimestamp();
|
||||
const clientversion = req.query.clientversion || req.query.version || req.query.clientVersion || null;
|
||||
|
||||
await db.pair(terminal.id, {
|
||||
token: strToken,
|
||||
clientserial: name,
|
||||
pairedAt,
|
||||
clientversion: clientversion ? String(clientversion).trim() : null,
|
||||
});
|
||||
|
||||
if (terminal.companyId) {
|
||||
|
||||
Reference in New Issue
Block a user