2025-06-23 10:22:27 -04:00
|
|
|
const mongoose = require('mongoose');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AgentCategory Schema - Dynamic agent category management
|
|
|
|
|
* Focused implementation for core features only
|
|
|
|
|
*/
|
|
|
|
|
const agentCategorySchema = new mongoose.Schema(
|
|
|
|
|
{
|
|
|
|
|
// Unique identifier for the category (e.g., 'general', 'hr', 'finance')
|
|
|
|
|
value: {
|
|
|
|
|
type: String,
|
|
|
|
|
required: true,
|
|
|
|
|
unique: true,
|
|
|
|
|
trim: true,
|
|
|
|
|
lowercase: true,
|
|
|
|
|
index: true,
|
|
|
|
|
},
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Display label for the category
|
|
|
|
|
label: {
|
|
|
|
|
type: String,
|
|
|
|
|
required: true,
|
|
|
|
|
trim: true,
|
|
|
|
|
},
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Description of the category
|
|
|
|
|
description: {
|
|
|
|
|
type: String,
|
|
|
|
|
trim: true,
|
|
|
|
|
default: '',
|
|
|
|
|
},
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Display order for sorting categories
|
|
|
|
|
order: {
|
|
|
|
|
type: Number,
|
|
|
|
|
default: 0,
|
|
|
|
|
index: true,
|
|
|
|
|
},
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Whether the category is active and should be displayed
|
|
|
|
|
isActive: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: true,
|
|
|
|
|
index: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
timestamps: true,
|
2025-06-11 22:55:07 +05:30
|
|
|
},
|
2025-06-23 10:22:27 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Indexes for performance
|
|
|
|
|
agentCategorySchema.index({ isActive: 1, order: 1 });
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get all active categories sorted by order
|
|
|
|
|
* @returns {Promise<AgentCategory[]>} Array of active categories
|
|
|
|
|
*/
|
2025-06-11 22:55:07 +05:30
|
|
|
agentCategorySchema.statics.getActiveCategories = function () {
|
|
|
|
|
return this.find({ isActive: true }).sort({ order: 1, label: 1 }).lean();
|
2025-06-23 10:22:27 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get categories with agent counts
|
|
|
|
|
* @returns {Promise<AgentCategory[]>} Categories with agent counts
|
|
|
|
|
*/
|
2025-06-11 22:55:07 +05:30
|
|
|
agentCategorySchema.statics.getCategoriesWithCounts = async function () {
|
|
|
|
|
const Agent = mongoose.model('Agent');
|
|
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Aggregate to get agent counts per category
|
|
|
|
|
const categoryCounts = await Agent.aggregate([
|
|
|
|
|
{ $match: { category: { $exists: true, $ne: null } } },
|
|
|
|
|
{ $group: { _id: '$category', count: { $sum: 1 } } },
|
|
|
|
|
]);
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Create a map for quick lookup
|
2025-06-11 22:55:07 +05:30
|
|
|
const countMap = new Map(categoryCounts.map((c) => [c._id, c.count]));
|
|
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
// Get all active categories and add counts
|
|
|
|
|
const categories = await this.getActiveCategories();
|
2025-06-11 22:55:07 +05:30
|
|
|
|
|
|
|
|
return categories.map((category) => ({
|
2025-06-23 10:22:27 -04:00
|
|
|
...category,
|
|
|
|
|
agentCount: countMap.get(category.value) || 0,
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get valid category values for Agent model validation
|
|
|
|
|
* @returns {Promise<string[]>} Array of valid category values
|
|
|
|
|
*/
|
2025-06-11 22:55:07 +05:30
|
|
|
agentCategorySchema.statics.getValidCategoryValues = function () {
|
|
|
|
|
return this.find({ isActive: true }).distinct('value').lean();
|
2025-06-23 10:22:27 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Seed initial categories from existing constants
|
|
|
|
|
*/
|
2025-06-11 22:55:07 +05:30
|
|
|
agentCategorySchema.statics.seedCategories = async function (categories) {
|
2025-06-23 10:22:27 -04:00
|
|
|
const operations = categories.map((category, index) => ({
|
|
|
|
|
updateOne: {
|
|
|
|
|
filter: { value: category.value },
|
|
|
|
|
update: {
|
|
|
|
|
$setOnInsert: {
|
|
|
|
|
value: category.value,
|
|
|
|
|
label: category.label || category.value,
|
|
|
|
|
description: category.description || '',
|
|
|
|
|
order: category.order || index,
|
|
|
|
|
isActive: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
upsert: true,
|
|
|
|
|
},
|
|
|
|
|
}));
|
2025-06-11 22:55:07 +05:30
|
|
|
|
2025-06-23 10:22:27 -04:00
|
|
|
return this.bulkWrite(operations);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AgentCategory = mongoose.model('AgentCategory', agentCategorySchema);
|
|
|
|
|
|
2025-06-11 22:55:07 +05:30
|
|
|
module.exports = AgentCategory;
|