This commit is contained in:
odzugkoev
2026-05-01 10:48:11 -04:00
parent 1b40187ade
commit 26badf8e6a
3 changed files with 34 additions and 13 deletions

View File

@@ -1,6 +1,13 @@
const config = require('./config'); const config = require('./config');
const apiClient = require('./api-client'); const apiClient = require('./api-client');
function parseOptionalNonNegativeNumber(value) {
if (value === undefined || value === null || value === '') return null;
const parsed = Number(value);
if (!Number.isFinite(parsed) || parsed < 0) return null;
return parsed;
}
class AbandonedCallPoller { class AbandonedCallPoller {
constructor(database, printer) { constructor(database, printer) {
this.db = database; this.db = database;
@@ -53,7 +60,7 @@ class AbandonedCallPoller {
const result = await apiClient.getAbandonedCalls( const result = await apiClient.getAbandonedCalls(
appConfig.authToken, appConfig.authToken,
appConfig.selectedBotId, appConfig.selectedBotId,
{ limit: 50 } { limit: 200 }
); );
if (result.error) { if (result.error) {
@@ -98,18 +105,22 @@ class AbandonedCallPoller {
const printerConfigs = this.db.getAbandonedCallPrinters(); const printerConfigs = this.db.getAbandonedCallPrinters();
if (!printerConfigs || printerConfigs.length === 0) return; if (!printerConfigs || printerConfigs.length === 0) return;
const cooldownSeconds = parseInt(appConfig.abandonedCallPrintCooldown, 10) || 300; const configuredCooldown = parseOptionalNonNegativeNumber(appConfig.abandonedCallPrintCooldown);
const lastPrintTime = this.db.getLastAbandonedCallPrintTime(); const cooldownSeconds = configuredCooldown === null ? 0 : configuredCooldown;
const now = Math.floor(Date.now() / 1000); const minScoreForPrint = parseOptionalNonNegativeNumber(appConfig.abandonedCallMinScoreForPrint);
let lastPrintTime = this.db.getLastAbandonedCallPrintTime();
const printablePriorities = new Set(['critical', 'high', 'medium']);
for (const call of calls) { for (const call of calls) {
if (!call || !call.id) continue;
if (this.db.hasAbandonedCallPrint(call.id)) continue; if (this.db.hasAbandonedCallPrint(call.id)) continue;
const priority = call.callback_priority || 'none'; const score = Number(call.callback_score) || 0;
if (!printablePriorities.has(priority)) continue; if (minScoreForPrint !== null && score < minScoreForPrint) {
console.log(`Abandoned call #${call.id}: skipping print (score ${score} below configured minimum ${minScoreForPrint})`);
continue;
}
const now = Math.floor(Date.now() / 1000);
if (lastPrintTime && (now - lastPrintTime) < cooldownSeconds) { if (lastPrintTime && (now - lastPrintTime) < cooldownSeconds) {
console.log(`Abandoned call #${call.id}: skipping print (cooldown active)`); console.log(`Abandoned call #${call.id}: skipping print (cooldown active)`);
continue; continue;
@@ -117,9 +128,18 @@ class AbandonedCallPoller {
try { try {
const result = await this.printer.printAbandonedCallReceipt(call, printerConfigs); const result = await this.printer.printAbandonedCallReceipt(call, printerConfigs);
const printedCount = result ? (result.successCount || printerConfigs.length) : 0; const printedCount = result && typeof result.successCount === 'number'
? result.successCount
: (result && result.success ? printerConfigs.length : 0);
if (result && result.success && printedCount > 0) {
this.db.addAbandonedCallPrint(call.id, printedCount); this.db.addAbandonedCallPrint(call.id, printedCount);
lastPrintTime = Math.floor(Date.now() / 1000);
console.log(`Abandoned call #${call.id}: printed on ${printedCount} printer(s)`); console.log(`Abandoned call #${call.id}: printed on ${printedCount} printer(s)`);
} else {
const message = result && result.error ? result.error : 'No printers succeeded';
console.error(`Abandoned call #${call.id}: print failed: ${message}`);
}
} catch (err) { } catch (err) {
console.error(`Abandoned call #${call.id}: print failed:`, err.message); console.error(`Abandoned call #${call.id}: print failed:`, err.message);
} }

View File

@@ -879,7 +879,8 @@ class DatabaseManager {
cleanOldAbandonedCallCache(maxAgeDays = 7) { cleanOldAbandonedCallCache(maxAgeDays = 7) {
const cutoff = Math.floor(Date.now() / 1000) - (maxAgeDays * 86400); const cutoff = Math.floor(Date.now() / 1000) - (maxAgeDays * 86400);
this.db.prepare('DELETE FROM abandoned_calls_cache WHERE updated_at < ?').run(cutoff); this.db.prepare('DELETE FROM abandoned_calls_cache WHERE updated_at < ?').run(cutoff);
this.db.prepare('DELETE FROM abandoned_call_prints WHERE printed_at < ?').run(cutoff); // Print records are dedupe state, not cache. Keep them so old calls do not
// reprint days later after the UI cache has been cleaned.
} }
close() { close() {

View File

@@ -1,6 +1,6 @@
{ {
"name": "kitchen-agent", "name": "kitchen-agent",
"version": "1.0.7", "version": "1.0.8",
"description": "Kitchen Agent for ThinkLink Food Order Management", "description": "Kitchen Agent for ThinkLink Food Order Management",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {