Wifiv2 / src /utils /tokenClientAlerts.js
Mbonea's picture
Use SMS TTL and priority defaults
fdd2359
Raw
History Blame Contribute Delete
3.58 kB
const db = require('../config/db');
const sms = require('../services/sms');
const messages = require('./messages');
const { canSendTenantNotification } = require('./notificationPreferences');
function formatDateTime(value) {
if (!value) return null;
const date = new Date(value);
if (Number.isNaN(date.getTime())) return null;
const parts = new Intl.DateTimeFormat('en-GB', {
timeZone: 'Africa/Dar_es_Salaam',
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
hour12: false,
}).formatToParts(date);
const part = type => parts.find(item => item.type === type)?.value || '';
return `${part('day')} ${part('month')} ${part('year')}, ${part('hour')}:${part('minute')} EAT`;
}
async function loadTokenContext(tokenId) {
return db.queryOne(
`SELECT t.id AS token_id, t.code AS token_code, t.locked_mac, t.expires_at,
d.id AS device_id, d.name AS device_name,
c.id AS client_id, c.phone AS client_phone,
p.phone AS payment_phone
FROM access_tokens t
JOIN devices d ON d.id = t.device_id
JOIN clients c ON c.id = t.client_id
LEFT JOIN payments p ON p.id = t.payment_id
WHERE t.id = ?
LIMIT 1`,
[tokenId]
);
}
async function alertWifiClient(eventType, tokenId, options = {}) {
try {
const token = await loadTokenContext(tokenId);
if (!token?.client_id) return false;
if (!(await canSendTenantNotification(token.client_id, 'purchase_alerts'))) return false;
const mac = options.mac || token.locked_mac || null;
const minutes = options.minutes || null;
const action = options.action || 'revoked';
const expiresAt = formatDateTime(options.expiresAt || token.expires_at);
let alertKey = null;
let module = 'tokens';
let content = null;
if (eventType === 'token_started') {
alertKey = `token-started-${token.token_id}-${String(mac || 'unknown').replace(/[^A-Za-z0-9]/g, '')}`;
content = messages.tokenStartedAlert(token.token_code, token.device_name, mac, expiresAt);
} else if (eventType === 'token_extended') {
alertKey = `token-extended-${token.token_id}-${Date.now()}`;
content = messages.tokenExtendedAlert(token.token_code, token.device_name, minutes, expiresAt);
} else if (eventType === 'token_revoked') {
alertKey = `token-revoked-${token.token_id}-${Date.now()}`;
content = messages.tokenRevokedAlert(token.token_code, token.device_name, action);
} else {
return false;
}
const result = await db.query(
`INSERT IGNORE INTO omada_alerts
(client_id, device_id, omada_alert_id, alert_key, module, level, content, device_mac, alert_time)
VALUES (?, ?, ?, ?, ?, 'info', ?, ?, NOW())`,
[
token.client_id,
token.device_id,
alertKey,
eventType,
module,
content,
mac,
]
);
if (Number(result?.affectedRows || 0) === 0) {
return false;
}
if (eventType === 'token_started' && token.payment_phone) {
const buyerMessage = messages.tokenStartedNotice(token.token_code, token.device_name, expiresAt);
sms.sendSMS(token.payment_phone, buyerMessage, {
ttl: 60 * 60,
priority: sms.priorities.high,
}).catch(err => {
console.error('[token-alert] buyer SMS failed:', err.message);
});
}
return true;
} catch (err) {
console.error('[token-alert] failed:', err.message, { eventType, tokenId });
return false;
}
}
module.exports = {
alertWifiClient,
};