nodebb-plugin-niki-loyalty 1.0.10 → 1.0.12
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 +58 -34
- package/package.json +1 -1
package/library.js
CHANGED
|
@@ -12,26 +12,37 @@ const SETTINGS = {
|
|
|
12
12
|
coffeeCost: 250
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
// ---
|
|
16
|
-
async function
|
|
15
|
+
// --- LOG FONKSİYONLARI ---
|
|
16
|
+
async function addUserLog(uid, type, amount, desc) {
|
|
17
17
|
const logEntry = {
|
|
18
|
-
|
|
18
|
+
ts: Date.now(),
|
|
19
19
|
type: type, // 'earn' veya 'spend'
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
amt: amount,
|
|
21
|
+
txt: desc
|
|
22
22
|
};
|
|
23
|
-
// Listeye ekle
|
|
23
|
+
// Listeye ekle ve son 50 işlemi tut
|
|
24
24
|
await db.listAppend(`niki:activity:${uid}`, logEntry);
|
|
25
|
-
|
|
26
|
-
// Son 50 işlemi tut, gerisini sil (Veritabanı şişmesin)
|
|
27
25
|
await db.listTrim(`niki:activity:${uid}`, -50, -1);
|
|
28
26
|
}
|
|
29
27
|
|
|
28
|
+
async function addKasaLog(staffUid, customerName, customerUid) {
|
|
29
|
+
const logEntry = {
|
|
30
|
+
ts: Date.now(),
|
|
31
|
+
staff: staffUid,
|
|
32
|
+
cust: customerName,
|
|
33
|
+
cuid: customerUid,
|
|
34
|
+
amt: SETTINGS.coffeeCost
|
|
35
|
+
};
|
|
36
|
+
// Kasa geçmişine ekle ve son 100 işlemi tut
|
|
37
|
+
await db.listAppend('niki:kasa:history', logEntry);
|
|
38
|
+
await db.listTrim('niki:kasa:history', -100, -1);
|
|
39
|
+
}
|
|
40
|
+
|
|
30
41
|
Plugin.init = async function (params) {
|
|
31
42
|
const router = params.router;
|
|
32
43
|
const middleware = params.middleware;
|
|
33
44
|
|
|
34
|
-
// 1. HEARTBEAT (Puan Kazanma
|
|
45
|
+
// 1. HEARTBEAT (Puan Kazanma)
|
|
35
46
|
router.post('/api/niki-loyalty/heartbeat', middleware.ensureLoggedIn, async (req, res) => {
|
|
36
47
|
const uid = req.uid;
|
|
37
48
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
@@ -45,16 +56,12 @@ Plugin.init = async function (params) {
|
|
|
45
56
|
|
|
46
57
|
await user.incrementUserFieldBy(uid, 'niki_points', SETTINGS.pointsPerHeartbeat);
|
|
47
58
|
await db.incrObjectFieldBy(dailyKey, 'score', SETTINGS.pointsPerHeartbeat);
|
|
48
|
-
|
|
49
|
-
// LOG EKLEME (Her 5 puan için log şişirmemek adına, sadece veritabanına sessizce işleyelim)
|
|
50
|
-
// Ancak kullanıcı her saniye log görmesin diye buraya eklemiyoruz.
|
|
51
|
-
// İstersen "Ders Çalışma Oturumu" bittiğinde toplu ekleyebiliriz ama şimdilik basit tutalım.
|
|
52
|
-
|
|
59
|
+
|
|
53
60
|
const newBalance = await user.getUserField(uid, 'niki_points');
|
|
54
61
|
return res.json({ earned: true, points: SETTINGS.pointsPerHeartbeat, total: newBalance });
|
|
55
62
|
});
|
|
56
63
|
|
|
57
|
-
// 2. WALLET DATA +
|
|
64
|
+
// 2. WALLET DATA (Cüzdan Bilgisi + Geçmiş)
|
|
58
65
|
router.get('/api/niki-loyalty/wallet-data', middleware.ensureLoggedIn, async (req, res) => {
|
|
59
66
|
const uid = req.uid;
|
|
60
67
|
const today = new Date().toISOString().slice(0, 10).replace(/-/g, '');
|
|
@@ -62,12 +69,9 @@ Plugin.init = async function (params) {
|
|
|
62
69
|
const [userData, dailyData, history] = await Promise.all([
|
|
63
70
|
user.getUserFields(uid, ['niki_points']),
|
|
64
71
|
db.getObject(`niki:daily:${uid}:${today}`),
|
|
65
|
-
db.getListRange(`niki:activity:${uid}`, 0, -1)
|
|
72
|
+
db.getListRange(`niki:activity:${uid}`, 0, -1)
|
|
66
73
|
]);
|
|
67
74
|
|
|
68
|
-
// Geçmişi ters çevir (En yeni en üstte)
|
|
69
|
-
const recentActivity = (history || []).reverse();
|
|
70
|
-
|
|
71
75
|
const currentPoints = parseInt(userData.niki_points) || 0;
|
|
72
76
|
const dailyScore = parseInt(dailyData ? dailyData.score : 0) || 0;
|
|
73
77
|
let dailyPercent = (dailyScore / SETTINGS.dailyCap) * 100;
|
|
@@ -78,11 +82,30 @@ Plugin.init = async function (params) {
|
|
|
78
82
|
dailyScore: dailyScore,
|
|
79
83
|
dailyCap: SETTINGS.dailyCap,
|
|
80
84
|
dailyPercent: dailyPercent,
|
|
81
|
-
history:
|
|
85
|
+
history: (history || []).reverse() // En yeniden eskiye
|
|
82
86
|
});
|
|
83
87
|
});
|
|
84
88
|
|
|
85
|
-
// 3.
|
|
89
|
+
// 3. KASA GEÇMİŞİ (Staff Dashboard)
|
|
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
|
+
const history = await db.getListRange('niki:kasa:history', 0, -1);
|
|
97
|
+
|
|
98
|
+
// Kullanıcı resimlerini de çekmek için zenginleştirme yapalım
|
|
99
|
+
const enrichedHistory = await Promise.all((history || []).reverse().map(async (item) => {
|
|
100
|
+
const uData = await user.getUserFields(item.cuid, ['picture']);
|
|
101
|
+
item.picture = uData.picture;
|
|
102
|
+
return item;
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
res.json(enrichedHistory);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 4. QR OLUŞTUR
|
|
86
109
|
router.post('/api/niki-loyalty/generate-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
87
110
|
const uid = req.uid;
|
|
88
111
|
const points = parseInt(await user.getUserField(uid, 'niki_points')) || 0;
|
|
@@ -96,7 +119,7 @@ Plugin.init = async function (params) {
|
|
|
96
119
|
return res.json({ success: true, token: token });
|
|
97
120
|
});
|
|
98
121
|
|
|
99
|
-
//
|
|
122
|
+
// 5. QR OKUT (Ödeme Alma)
|
|
100
123
|
router.post('/api/niki-loyalty/scan-qr', middleware.ensureLoggedIn, async (req, res) => {
|
|
101
124
|
const { token } = req.body;
|
|
102
125
|
|
|
@@ -108,28 +131,29 @@ Plugin.init = async function (params) {
|
|
|
108
131
|
if (!customerUid) return res.json({ success: false, message: 'Geçersiz Kod' });
|
|
109
132
|
|
|
110
133
|
const pts = parseInt(await user.getUserField(customerUid, 'niki_points')) || 0;
|
|
111
|
-
if (pts < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Bakiye
|
|
134
|
+
if (pts < SETTINGS.coffeeCost) return res.json({ success: false, message: 'Yetersiz Bakiye' });
|
|
112
135
|
|
|
113
|
-
//
|
|
136
|
+
// İŞLEM
|
|
114
137
|
await user.decrementUserFieldBy(customerUid, 'niki_points', SETTINGS.coffeeCost);
|
|
115
138
|
await db.delete(`niki:qr:${token}`);
|
|
116
139
|
|
|
117
|
-
//
|
|
118
|
-
await addLog(customerUid, 'spend', SETTINGS.coffeeCost, 'Kahve Harcaması');
|
|
119
|
-
|
|
140
|
+
// LOGLAMA (Detaylı metin ile)
|
|
120
141
|
const customerData = await user.getUserFields(customerUid, ['username', 'picture']);
|
|
142
|
+
|
|
143
|
+
// Öğrenciye: "Kahve Keyfi" yazsın
|
|
144
|
+
await addUserLog(customerUid, 'spend', SETTINGS.coffeeCost, 'Kahve Keyfi ☕');
|
|
145
|
+
|
|
146
|
+
// Kasaya: Kimin aldığı yazsın
|
|
147
|
+
await addKasaLog(req.uid, customerData.username, customerUid);
|
|
148
|
+
|
|
121
149
|
return res.json({ success: true, customer: customerData, message: 'Onaylandı!' });
|
|
122
150
|
});
|
|
123
151
|
|
|
124
|
-
//
|
|
125
|
-
// Buraya "Kazanma Logu" ekleyelim ki tabloda görünsün.
|
|
126
|
-
// Client tarafındaki "heartbeat" çok sık çalıştığı için veritabanını şişirmemek adına
|
|
127
|
-
// oraya log koymadık. Ama günlük hedefe ulaşınca veya manuel eklenince log düşebiliriz.
|
|
128
|
-
|
|
129
|
-
// NIKI KASA SAYFASI
|
|
152
|
+
// SAYFA ROTASI
|
|
130
153
|
routeHelpers.setupPageRoute(router, '/niki-kasa', middleware, [], async (req, res) => {
|
|
131
154
|
const isAdmin = await user.isAdministrator(req.uid);
|
|
132
|
-
|
|
155
|
+
const isMod = await user.isGlobalModerator(req.uid);
|
|
156
|
+
if (!isAdmin && !isMod) return res.render('403', {});
|
|
133
157
|
res.render('niki-kasa', { title: 'Niki Kasa' });
|
|
134
158
|
});
|
|
135
159
|
};
|