nodebb-plugin-niki-loyalty 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/library.js +56 -47
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -8,37 +8,41 @@ const Plugin = {};
|
|
|
8
8
|
|
|
9
9
|
const SETTINGS = {
|
|
10
10
|
pointsPerHeartbeat: 5,
|
|
11
|
-
dailyCap:
|
|
11
|
+
dailyCap: 2500000,
|
|
12
12
|
coffeeCost: 250
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
// ---
|
|
16
|
-
async function
|
|
15
|
+
// --- LOG TUTMA YARDIMCILARI ---
|
|
16
|
+
async function addUserLog(uid, type, amount, desc) {
|
|
17
17
|
const logEntry = {
|
|
18
18
|
ts: Date.now(),
|
|
19
|
-
|
|
19
|
+
type: type, // 'earn' (kazanç) veya 'spend' (harcama)
|
|
20
|
+
amt: amount,
|
|
21
|
+
txt: desc
|
|
22
|
+
};
|
|
23
|
+
// Öğrencinin listesine ekle (Son 50 işlem)
|
|
24
|
+
await db.listAppend(`niki:activity:${uid}`, logEntry);
|
|
25
|
+
await db.listTrim(`niki:activity:${uid}`, -50, -1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function addKasaLog(staffUid, customerName, customerUid) {
|
|
29
|
+
const logEntry = {
|
|
30
|
+
ts: Date.now(),
|
|
31
|
+
staff: staffUid,
|
|
20
32
|
cust: customerName,
|
|
21
|
-
|
|
33
|
+
cuid: customerUid,
|
|
22
34
|
amt: SETTINGS.coffeeCost
|
|
23
35
|
};
|
|
24
|
-
// Kasa
|
|
36
|
+
// Kasa defterine ekle (Son 100 işlem)
|
|
25
37
|
await db.listAppend('niki:kasa:history', logEntry);
|
|
26
|
-
// Son 100 işlemi tut, gerisini sil (Veritabanı temizliği)
|
|
27
38
|
await db.listTrim('niki:kasa:history', -100, -1);
|
|
28
39
|
}
|
|
29
40
|
|
|
30
|
-
// --- YARDIMCI: ÖĞRENCİ GÜNLÜĞÜNE EKLE ---
|
|
31
|
-
async function addUserLog(uid, type, amount, desc) {
|
|
32
|
-
const logEntry = { timestamp: Date.now(), type: type, amount: amount, desc: desc };
|
|
33
|
-
await db.listAppend(`niki:activity:${uid}`, logEntry);
|
|
34
|
-
await db.listTrim(`niki:activity:${uid}`, -50, -1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
41
|
Plugin.init = async function (params) {
|
|
38
42
|
const router = params.router;
|
|
39
43
|
const middleware = params.middleware;
|
|
40
44
|
|
|
41
|
-
// 1. HEARTBEAT (
|
|
45
|
+
// 1. HEARTBEAT (Ders Çalışma Puanı)
|
|
42
46
|
router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
|
|
43
47
|
const uid = req.uid;
|
|
44
48
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
@@ -57,7 +61,7 @@ Plugin.init = async function (params) {
|
|
|
57
61
|
return res.json({ earned: true, points: SETTINGS.pointsPerHeartbeat, total: newBalance });
|
|
58
62
|
});
|
|
59
63
|
|
|
60
|
-
// 2. WALLET DATA (Öğrenci Cüzdanı)
|
|
64
|
+
// 2. WALLET DATA (Öğrenci Cüzdanı ve Geçmişi)
|
|
61
65
|
router.get('/api/niki-loyalty/wallet-data', middleware.ensureLoggedIn, async (req, res) => {
|
|
62
66
|
const uid = req.uid;
|
|
63
67
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
@@ -65,7 +69,7 @@ Plugin.init = async function (params) {
|
|
|
65
69
|
const [userData, dailyData, history] = await Promise.all([
|
|
66
70
|
user.getUserFields(uid, ['niki_points']),
|
|
67
71
|
db.getObject(`niki:daily:${uid}:${today}`),
|
|
68
|
-
db.getListRange(`niki:activity:${uid}`, 0, -1)
|
|
72
|
+
db.getListRange(`niki:activity:${uid}`, 0, -1) // Geçmişi çek
|
|
69
73
|
]);
|
|
70
74
|
|
|
71
75
|
const currentPoints = parseInt(userData.niki_points) || 0;
|
|
@@ -78,75 +82,80 @@ Plugin.init = async function (params) {
|
|
|
78
82
|
dailyScore: dailyScore,
|
|
79
83
|
dailyCap: SETTINGS.dailyCap,
|
|
80
84
|
dailyPercent: dailyPercent,
|
|
81
|
-
history: (history || []).reverse()
|
|
85
|
+
history: (history || []).reverse() // En yeniden eskiye sırala
|
|
82
86
|
});
|
|
83
87
|
});
|
|
84
88
|
|
|
85
|
-
// 3.
|
|
89
|
+
// 3. KASA GEÇMİŞİ (Personel Dashboard İçin) - EKSİK OLAN BUYDU
|
|
90
|
+
router.get('/api/niki-loyalty/kasa-history', middleware.ensureLoggedIn, async (req, res) => {
|
|
91
|
+
const isAdmin = await user.isAdministrator(req.uid);
|
|
92
|
+
const isMod = await user.isGlobalModerator(req.uid);
|
|
93
|
+
|
|
94
|
+
if (!isAdmin && !isMod) return res.status(403).json([]);
|
|
95
|
+
|
|
96
|
+
// Veritabanından listeyi çek
|
|
97
|
+
const history = await db.getListRange('niki:kasa:history', 0, -1);
|
|
98
|
+
|
|
99
|
+
// Kullanıcı resimlerini de ekleyerek zenginleştir
|
|
100
|
+
const enrichedHistory = await Promise.all((history || []).reverse().map(async (item) => {
|
|
101
|
+
const uData = await user.getUserFields(item.cuid, ['picture']);
|
|
102
|
+
item.picture = uData.picture;
|
|
103
|
+
return item;
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
res.json(enrichedHistory);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// 4. QR TOKEN ÜRET (Öğrenci Butona Basınca)
|
|
86
110
|
router.post('/api/niki-loyalty/generate-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
87
111
|
const uid = req.uid;
|
|
88
112
|
const points = parseInt(await user.getUserField(uid, 'niki_points')) || 0;
|
|
113
|
+
|
|
89
114
|
if (points < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Yetersiz Puan' });
|
|
90
115
|
|
|
91
116
|
const token = Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
92
117
|
await db.set(`niki:qr:${token}`, uid);
|
|
93
|
-
await db.expire(`niki:qr:${token}`, 120);
|
|
118
|
+
await db.expire(`niki:qr:${token}`, 120); // 2 dakika süre
|
|
94
119
|
|
|
95
120
|
return res.json({ success: true, token: token });
|
|
96
121
|
});
|
|
97
122
|
|
|
98
|
-
//
|
|
123
|
+
// 5. QR OKUTMA (Personel Tarayınca)
|
|
99
124
|
router.post('/api/niki-loyalty/scan-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
100
125
|
const { token } = req.body;
|
|
101
126
|
|
|
102
|
-
// Yetki Kontrolü
|
|
103
127
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
104
128
|
const isMod = await user.isGlobalModerator(req.uid);
|
|
105
129
|
if (!isAdmin && !isMod) return res.status(403).json({ success: false, message: 'Yetkisiz' });
|
|
106
130
|
|
|
107
|
-
// Token Doğrula
|
|
108
131
|
const customerUid = await db.get(`niki:qr:${token}`);
|
|
109
|
-
if (!customerUid) return res.json({ success: false, message: 'Geçersiz
|
|
132
|
+
if (!customerUid) return res.json({ success: false, message: 'Kod Geçersiz veya Süresi Dolmuş' });
|
|
110
133
|
|
|
111
|
-
// Puan Kontrolü
|
|
112
134
|
const pts = parseInt(await user.getUserField(customerUid, 'niki_points')) || 0;
|
|
113
135
|
if (pts < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Yetersiz Bakiye' });
|
|
114
136
|
|
|
115
|
-
// İŞLEMİ YAP
|
|
137
|
+
// İŞLEMİ YAP (Puan düş)
|
|
116
138
|
await user.decrementUserFieldBy(customerUid, 'niki_points', SETTINGS.coffeeCost);
|
|
117
139
|
await db.delete(`niki:qr:${token}`);
|
|
118
140
|
|
|
119
|
-
// LOGLARI
|
|
141
|
+
// LOGLARI KAYDET (Bu kısım önceden yoktu, o yüzden geçmiş boş geliyordu)
|
|
120
142
|
const customerData = await user.getUserFields(customerUid, ['username', 'picture']);
|
|
121
143
|
|
|
122
|
-
// 1. Öğrencinin
|
|
123
|
-
await addUserLog(customerUid, 'spend', SETTINGS.coffeeCost, 'Kahve
|
|
144
|
+
// 1. Öğrencinin Cüzdanına: "Kahve Keyfi -250"
|
|
145
|
+
await addUserLog(customerUid, 'spend', SETTINGS.coffeeCost, 'Kahve Keyfi ☕');
|
|
124
146
|
|
|
125
|
-
// 2. Kasa Defterine
|
|
126
|
-
await addKasaLog(req.uid, customerData.username,
|
|
127
|
-
|
|
128
|
-
return res.json({ success: true, customer: customerData, message: 'Onaylandı!' });
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// 5. KASA GEÇMİŞİNİ GETİR (YENİ API)
|
|
132
|
-
router.get('/api/niki-loyalty/kasa-history', middleware.ensureLoggedIn, async (req, res) => {
|
|
133
|
-
const isAdmin = await user.isAdministrator(req.uid);
|
|
134
|
-
const isMod = await user.isGlobalModerator(req.uid);
|
|
135
|
-
if (!isAdmin && !isMod) return res.status(403).json([]);
|
|
147
|
+
// 2. Kasa Defterine: "Ahmet'ten Ödeme Alındı"
|
|
148
|
+
await addKasaLog(req.uid, customerData.username, customerUid);
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
const history = await db.getListRange('niki:kasa:history', 0, -1);
|
|
139
|
-
|
|
140
|
-
// Ters çevir (En yeni en üstte)
|
|
141
|
-
res.json((history || []).reverse());
|
|
150
|
+
return res.json({ success: true, customer: customerData, message: 'İşlem Başarılı!' });
|
|
142
151
|
});
|
|
143
152
|
|
|
144
|
-
// SAYFA
|
|
153
|
+
// SAYFA ROTASI
|
|
145
154
|
routeHelpers.setupPageRoute(router, '/niki-kasa', middleware, [], async (req, res) => {
|
|
146
155
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
147
156
|
const isMod = await user.isGlobalModerator(req.uid);
|
|
148
157
|
if (!isAdmin && !isMod) return res.render('403', {});
|
|
149
|
-
res.render('niki-kasa', { title: 'Niki Kasa' });
|
|
158
|
+
res.render('niki-kasa', { title: 'Niki Kasa Terminali' });
|
|
150
159
|
});
|
|
151
160
|
};
|
|
152
161
|
|