From a1f099a9368acd24b76dd097e65e2d85fa419ff9 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Wed, 24 Dec 2025 19:04:30 +0330 Subject: [PATCH] aggragation for pagination and filters --- pages/admin/gps/installed-device/index.vue | 15 ++- server/controllers/GPS.InstalledDevice.js | 115 +++++++++++++++------ 2 files changed, 96 insertions(+), 34 deletions(-) diff --git a/pages/admin/gps/installed-device/index.vue b/pages/admin/gps/installed-device/index.vue index 5c63e62..78fe3dc 100644 --- a/pages/admin/gps/installed-device/index.vue +++ b/pages/admin/gps/installed-device/index.vue @@ -93,7 +93,7 @@ @@ -250,6 +250,19 @@ export default { } }, methods: { + getLocationText(user) { + if (!user) return '' + + const province = typeof user.province_name === 'string' + ? user.province_name + : user.province_name?.provinceName || '' + + const city = typeof user.city_name === 'string' + ? user.city_name + : user.city_name?.cityName || '' + + return [province, city].filter(Boolean).join(', ') || '-' + }, async fetchData() { this.loading = true try { diff --git a/server/controllers/GPS.InstalledDevice.js b/server/controllers/GPS.InstalledDevice.js index 9daff95..18d7a0f 100644 --- a/server/controllers/GPS.InstalledDevice.js +++ b/server/controllers/GPS.InstalledDevice.js @@ -188,53 +188,102 @@ module.exports.getAllForAdmin = async (req, res) => { const rows = parseInt(req.query.rows) || 10 const skip = (page - 1) * rows - // Build status filter - const filter = {} + const match = {} + if (filterType !== 'all') { - let statusValue - if (filterType === 'rej') statusValue = 2 - else if (filterType === 'accept') statusValue = 1 - else if (filterType === 'pend') statusValue = 0 - - if (statusValue !== undefined) { - filter.status = statusValue + const map = { pend: 0, accept: 1, rej: 2 } + if (map[filterType] !== undefined) { + match.status = map[filterType] } } - // Fetch data with status filter (search will be done after populate) - let data = await InstalledDevice.find(filter) - .sort({ created_at: -1 }) - .populate('deviceId') - .populate('userId', 'shopName national_code first_name last_name mobile_number city_name province_name') - - // Filter by IMEI and deviceId.model if search is provided (needs to be done after populate) if (search) { - const searchLower = search.toLowerCase() - data = data.filter(item => { - const imeiMatch = item.IMEI && item.IMEI.toLowerCase().includes(searchLower) - const modelMatch = item.deviceId && item.deviceId.model && item.deviceId.model.toLowerCase().includes(searchLower) - return imeiMatch || modelMatch - }) + match.$or = [ + { IMEI: { $regex: search, $options: 'i' } } + ] } - // Calculate pagination - const totalDocuments = data.length + const pipeline = [ + { $match: match }, + + { + $lookup: { + from: 'devices', + localField: 'deviceId', + foreignField: '_id', + as: 'deviceId' + } + }, + { $unwind: { path: '$deviceId', preserveNullAndEmptyArrays: true } }, + + ...(search + ? [{ + $match: { + $or: [ + { 'deviceId.model': { $regex: search, $options: 'i' } }, + { IMEI: { $regex: search, $options: 'i' } } + ] + } + }] + : []), + + { + $lookup: { + from: 'usergps', + let: { userIdStr: '$userId' }, + pipeline: [ + { + $match: { + $expr: { + $and: [ + { $ne: ['$$userIdStr', null] }, + { $ne: ['$$userIdStr', ''] }, + { + $eq: [ + '$_id', + { + $convert: { + input: '$$userIdStr', + to: 'objectId', + onError: null, + onNull: null + } + } + ] + } + ] + } + } + } + ], + as: 'userId' + } + }, + { $unwind: { path: '$userId', preserveNullAndEmptyArrays: true } }, + + { $sort: { created_at: -1 } }, + + { + $facet: { + data: [{ $skip: skip }, { $limit: rows }], + totalCount: [{ $count: 'count' }] + } + } + ] + + const result = await InstalledDevice.aggregate(pipeline) + + const data = result[0].data + const totalDocuments = result[0].totalCount[0]?.count || 0 const totalPages = Math.ceil(totalDocuments / rows) - // Apply pagination - const paginatedData = data.slice(skip, skip + rows) - - res.status(200).json({ - data: paginatedData, - totalDocuments, - totalPages - }) + res.status(200).json({ data, totalDocuments, totalPages }) } catch (error) { - console.error('Error:', error.message) res.status(500).json({ message: 'Server Error', error: error.message }) } } + module.exports.updateInstalled = [ [ param('id').notEmpty().isMongoId().withMessage('لطفا ایدی را وارد یا تصحیح کنید'),