Spaces:
Paused
Paused
File size: 6,217 Bytes
545959e 8319e46 545959e 8ab5905 545959e 141007f 545959e 586511a 545959e ed9a46f 545959e ed9a46f 545959e ed9a46f 545959e ed9a46f 545959e ed9a46f 141007f ed9a46f 545959e 8319e46 545959e 8319e46 545959e | 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | const { Scenes, Markup } = require('telegraf');
const Product = require('../../models/Product');
const User = require('../../models/User');
const flashSaleScene = new Scenes.WizardScene(
'admin_flash_sale',
// Step 1: Menu
async (ctx) => {
const text = "π₯ **Flash Sale (Aksiya) Boshqaruvi**\n\nNima qilmoqchisiz?";
const buttons = [
[Markup.button.callback("π Aksiya Boshlash", "start_sale")],
[Markup.button.callback("π Aksiyani To'xtatish (Narxlarni tiklash)", "stop_sale")],
[Markup.button.callback("π Asosiy menyu", "back_dashboard")]
];
if (ctx.callbackQuery) {
await ctx.editMessageText(text, { parse_mode: 'Markdown', ...Markup.inlineKeyboard(buttons) });
} else {
await ctx.replyWithMarkdown(text, Markup.inlineKeyboard(buttons));
}
return ctx.wizard.next();
},
// Step 2: Handle Choice
async (ctx) => {
if (!ctx.callbackQuery && !ctx.message) return;
const txt = ctx.message ? ctx.message.text : '';
if (txt === '/start' || txt === 'β Bekor qilish') return ctx.scene.leave();
if (ctx.callbackQuery) {
const data = ctx.callbackQuery.data;
if (data === 'back_dashboard') {
await ctx.scene.leave();
const adminController = require('../../controllers/adminController');
return adminController.showDashboard(ctx);
}
if (data === 'stop_sale') {
await ctx.answerCbQuery("Narxlar tiklanmoqda...");
// Revert Logic
const products = await Product.find({ originalPrice: { $ne: null } });
if (products.length === 0) {
await ctx.reply("β οΈ Tiklash uchun o'zgartirilgan mahsulotlar topilmadi.");
return ctx.scene.leave();
}
let count = 0;
for (let p of products) {
p.price = p.originalPrice;
p.originalPrice = null; // Clear history
p.discountPercent = 0; // Reset discount
await p.save();
count++;
}
await ctx.reply(`β
<b>Aksiya tugatildi.</b>\n${count} ta mahsulot narxi joyiga qaytarildi.`, { parse_mode: 'HTML' });
return ctx.scene.leave();
}
if (data === 'start_sale') {
await ctx.reply("π <b>Chegirma foizini kiriting:</b>\nMasalan: 10 (10% arzonlashadi)\n\n<i>Eslatma: Bu barcha mahsulotlarga ta'sir qiladi!</i>", { parse_mode: 'HTML', ...Markup.keyboard([['β Bekor qilish']]).resize() });
ctx.wizard.state.action = 'get_percent';
return ctx.wizard.next();
}
}
},
// Step 3: Apply Discount
async (ctx) => {
const txt = ctx.message ? ctx.message.text : '';
if (txt === 'β Bekor qilish') {
await ctx.reply("Bekor qilindi.", Markup.removeKeyboard());
await ctx.scene.leave();
const adminController = require('../../controllers/adminController');
return adminController.showDashboard(ctx);
}
const percent = parseInt(txt);
if (isNaN(percent) || percent <= 0 || percent >= 100) {
await ctx.reply("β οΈ Iltimos, to'g'ri foiz kiriting (1-99 oralig'ida).");
return;
}
await ctx.reply(`β³ ${percent}% chegirma qo'llanmoqda...`);
const products = await Product.find({});
let count = 0;
for (let p of products) {
try {
// Skip invalid products (corrupt data)
if (!p.id || !p.name) {
console.warn(`Skipping invalid product (Missing ID/Name): ${p._id}`);
continue;
}
// Only update if not already discounted (prevent double discount)
// Or overwrite? Let's assume overwrite logic:
// If already has originalPrice, use THAT as base. If not, use current price.
let basePrice = p.originalPrice || p.price;
// Save original price if not already saved
if (!p.originalPrice) {
p.originalPrice = basePrice;
}
// Calculate new price
const discountAmount = (basePrice * percent) / 100;
p.price = Math.round(basePrice - discountAmount);
p.discountPercent = percent; // Save percent display
await p.save();
count++;
} catch (err) {
console.error(`Failed to update product ${p.id}:`, err.message);
}
}
const User = require('../../models/User'); // Ensure User model is required at top
// ... inside the scene ...
await ctx.reply(`β
<b>Aksiya Boshlandi!</b>\n\n${count} ta mahsulot narxi ${percent}% ga arzonlashtirildi.`, { parse_mode: 'HTML', ...Markup.removeKeyboard() });
// --- BROADCAST NOTIFICATION ---
await ctx.reply("π’ Foydalanuvchilarga xabar yuborilmoqda...");
const users = await User.find({});
let sent = 0;
const message = `π₯ <b>DIQQAT AKSIYA!</b>\n\nπ Do'konimizda <b>FLASH SALE</b> boshlandi!\n\nπ Barcha mahsulotlarga <b>${percent}% CHEGIRMA</b> e'lon qilindi.\n\nHoziroq xarid qiling, aksiya vaqti chegaralangan! β³\n\nπππ`;
for (let user of users) {
try {
await ctx.telegram.sendMessage(user.id, message, { parse_mode: 'HTML' });
sent++;
} catch (e) {
// User blocked bot or inactive
}
// Small delay to prevent spam flood
await new Promise(r => setTimeout(r, 50));
}
await ctx.reply(`π’ Xabar ${sent} ta foydalanuvchiga yuborildi.`);
await ctx.scene.leave();
const adminController = require('../../controllers/adminController');
return adminController.showDashboard(ctx);
}
);
module.exports = flashSaleScene;
|