File size: 3,583 Bytes
d8fc0a7
 
 
 
 
 
 
 
 
8c5d98c
 
d8fc0a7
 
 
 
 
 
8c5d98c
 
 
 
 
d8fc0a7
 
 
 
 
 
8c5d98c
 
d8fc0a7
 
 
8c5d98c
d8fc0a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65d167b
d8fc0a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c5d98c
 
fdd2359
 
 
 
8c5d98c
d8fc0a7
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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,
};