full
This commit is contained in:
100
controllers/panel/notifications/notificationsController.js
Normal file
100
controllers/panel/notifications/notificationsController.js
Normal file
@@ -0,0 +1,100 @@
|
||||
const AdminBroadcastModel = require('../../../models/AdminBroadcastModel')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const { sendPushToTokens } = require('../../../utils/pushNotification')
|
||||
|
||||
/** ارسال اعلان همگانی — مثل ارسال پیامک، به همهی کاربران */
|
||||
const createBroadcast = async (req, res, next) => {
|
||||
try {
|
||||
const { title, body } = req.body
|
||||
if (!title || !body) {
|
||||
return res.status(400).json({ message: 'عنوان و متن اعلان الزامی است' })
|
||||
}
|
||||
|
||||
const users = await UserModel.find({}).select('_id fcm_tokens fcm_web_tokens').lean()
|
||||
|
||||
const broadcast = await AdminBroadcastModel.create({
|
||||
title,
|
||||
body,
|
||||
recipientCount: users.length,
|
||||
sentBy: req.admin?._id
|
||||
})
|
||||
|
||||
if (users.length > 0) {
|
||||
await NotificationModel.insertMany(
|
||||
users.map((u) => ({
|
||||
user_id: u._id,
|
||||
type: 'admin_broadcast',
|
||||
title,
|
||||
description: body,
|
||||
broadcast_id: broadcast._id
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
const tokens = users.flatMap((u) => [...(u.fcm_tokens || []), ...(u.fcm_web_tokens || [])])
|
||||
if (tokens.length > 0) {
|
||||
sendPushToTokens(tokens, {
|
||||
title,
|
||||
description: body,
|
||||
type: 'admin_broadcast',
|
||||
data: { broadcastId: String(broadcast._id) }
|
||||
}).catch((err) => console.error('[notificationsController] ارسال پوش همگانی خطا:', err.message))
|
||||
}
|
||||
|
||||
res.status(201).json({ broadcast })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getBroadcasts = async (req, res, next) => {
|
||||
try {
|
||||
const { page = 1, limit = 20 } = req.query
|
||||
const options = {
|
||||
page: parseInt(page, 10) || 1,
|
||||
limit: parseInt(limit, 10) || 20,
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
const result = await AdminBroadcastModel.paginate({}, options)
|
||||
const broadcasts = result.docs.map((b) => ({
|
||||
...b._doc,
|
||||
createdAtJalali: jMoment(b.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
}))
|
||||
|
||||
res.json({
|
||||
broadcasts,
|
||||
totalPages: result.totalPages,
|
||||
totalItems: result.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getBroadcastDetail = async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params
|
||||
const broadcast = await AdminBroadcastModel.findById(id).lean()
|
||||
if (!broadcast) return res.status(404).json({ message: 'اعلان یافت نشد' })
|
||||
|
||||
const [seenCount, clickedCount] = await Promise.all([
|
||||
NotificationModel.countDocuments({ broadcast_id: id, push_delivered_seen: true }),
|
||||
NotificationModel.countDocuments({ broadcast_id: id, push_clicked: true })
|
||||
])
|
||||
|
||||
res.json({
|
||||
broadcast: {
|
||||
...broadcast,
|
||||
createdAtJalali: jMoment(broadcast.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
},
|
||||
seenCount,
|
||||
clickedCount
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { createBroadcast, getBroadcasts, getBroadcastDetail }
|
||||
Reference in New Issue
Block a user