aggragation for pagination and filters

This commit is contained in:
2025-12-24 19:04:30 +03:30
parent 285ee03ae5
commit a1f099a936
2 changed files with 96 additions and 34 deletions
+14 -1
View File
@@ -93,7 +93,7 @@
<el-table-column label="محل سکونت" width="">
<template slot-scope="scope">
{{ scope?.row?.userId?.province_name + ', ' + scope?.row?.userId?.city_name }}
{{ getLocationText(scope?.row?.userId) }}
</template>
</el-table-column>
@@ -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 {
+82 -33
View File
@@ -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('لطفا ایدی را وارد یا تصحیح کنید'),