UNPKG

pms-analysis-reports-mcp-server

Version:

PMS analysis reports server handling maintenance reports, equipment analysis, compliance tracking, and performance metrics with ERP access for data extraction

261 lines 10.6 kB
/** * Company Name Filtering Utilities * Helper functions for filtering data based on company IMO numbers * * ============================================================================ * OLD IMPLEMENTATION (COMMENTED OUT - REPLACED BY OPTIMIZED VERSION) * ============================================================================ * The old implementation has been replaced with an optimized version that includes: * - In-memory caching with TTL (5 minutes) * - MongoDB connection pooling * - Set-based IMO lookups (O(1) instead of O(n)) * - Cached environment variables and config * ============================================================================ */ import { MongoClient } from 'mongodb'; import { getConfig } from './config.js'; import { logger } from './logger.js'; /** * Check if IMO filtering should be bypassed for admin companies */ function shouldBypassImoFiltering(companyName) { const adminCompanies = ['admin', 'administrator', 'superadmin', 'syia']; return adminCompanies.some(admin => companyName.toLowerCase().includes(admin.toLowerCase())); } /** * Optimized Company Filter Manager with caching and connection pooling */ class CompanyFilterManager { constructor() { // Cache structure: Map<"companyName:dbName", { imos: Set<string>, timestamp: number }> this.imoCache = new Map(); // Connection pool: Map<"mongoUri", MongoClient> this.mongoClients = new Map(); // Cache TTL: 5 minutes this.CACHE_TTL = 5 * 60 * 1000; // Cached config values this.cachedCompanyName = null; this.cachedDbConfig = null; } /** * Get company name (cached) */ getCompanyName() { if (this.cachedCompanyName === null) { this.cachedCompanyName = getConfig().companyName || ''; } return this.cachedCompanyName || ''; } /** * Get database configuration (cached) */ getDbConfig() { if (this.cachedDbConfig === null) { this.cachedDbConfig = { dbName: process.env.GROUP_DETAILS_DB_NAME || process.env.FLEET_DISTRIBUTION_DB_NAME || process.env.COMPANY_DB_NAME || '', mongoUri: process.env.GROUP_DETAILS_MONGO_URI || process.env.FLEET_DISTRIBUTION_MONGO_URI || process.env.COMPANY_DB_URI || '' }; } return this.cachedDbConfig; } /** * Get or create MongoDB client (connection pooling) */ async getMongoClient(mongoUri) { if (!this.mongoClients.has(mongoUri)) { const client = new MongoClient(mongoUri, { maxPoolSize: 10, minPoolSize: 2, maxIdleTimeMS: 30000 }); await client.connect(); this.mongoClients.set(mongoUri, client); } return this.mongoClients.get(mongoUri); } /** * Get company IMO set with caching (returns Set for O(1) lookups) */ async getCompanyImoSet(companyName, dbName, mongoUri, collectionName = 'common_group_details') { const cacheKey = `${companyName}:${dbName}`; const cached = this.imoCache.get(cacheKey); // Return from cache if valid if (cached && (Date.now() - cached.timestamp) < this.CACHE_TTL) { return cached.imos; } // Fetch from MongoDB if (!dbName || !mongoUri || !companyName) { return new Set(); } try { const client = await this.getMongoClient(mongoUri); const db = client.db(dbName); const collection = db.collection(collectionName); // Try both companyName and groupName fields for compatibility const result = await collection.findOne({ $or: [{ companyName: companyName }, { groupName: companyName }] }, { projection: { imoList: 1, imo: 1, _id: 0 } }); const imoSet = new Set(result?.imoList?.map((imo) => String(imo)) || []); // append imo to imoSet if (result?.imo) { imoSet.add(String(result.imo)); } // Update cache this.imoCache.set(cacheKey, { imos: imoSet, timestamp: Date.now() }); return imoSet; } catch (error) { logger.error(`Error fetching IMO numbers for company ${companyName}:`, error); return new Set(); } } /** * Validate if an IMO belongs to the company (optimized) */ async isValidImoForCompany(imo, companyName, dbName, mongoUri) { const finalCompanyName = companyName || this.getCompanyName(); if (!finalCompanyName) { return true; // If no company name, allow all } // Bypass validation for "Synergy" company if (finalCompanyName === "Synergy") { return true; } // Bypass validation for admin companies if (shouldBypassImoFiltering(finalCompanyName)) { return true; } // Use provided dbName/mongoUri or fallback to cached config values const configValues = this.getDbConfig(); const finalDbName = dbName || configValues.dbName; const finalMongoUri = mongoUri || configValues.mongoUri; if (!finalDbName || !finalMongoUri) { logger.warn('Company IMO validation skipped: Missing database configuration'); return true; // Allow if config is missing } try { const imoSet = await this.getCompanyImoSet(finalCompanyName, finalDbName, finalMongoUri); return imoSet.has(String(imo)); } catch (error) { logger.error(`Error validating IMO for company: ${error}`); return true; // Allow on error to prevent blocking } } /** * Update Typesense filter with company IMO numbers (optimized) */ async updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri) { const companyName = this.getCompanyName(); if (!companyName) { return filter; } // Bypass filtering for "Synergy" company if (companyName === "Synergy") { return filter; } // Bypass filtering for admin companies if (shouldBypassImoFiltering(companyName)) { return filter; } // Use provided dbName/mongoUri or fallback to cached config values const configValues = this.getDbConfig(); const finalDbName = dbName || configValues.dbName; const finalMongoUri = mongoUri || configValues.mongoUri; if (!finalDbName || !finalMongoUri) { logger.warn('Company IMO filtering skipped: Missing database configuration'); return filter; } try { const imoSet = await this.getCompanyImoSet(companyName, finalDbName, finalMongoUri); if (imoSet.size === 0) { logger.warn(`No IMO numbers found for company: ${companyName}`); // If no company IMO numbers found, return original filter (old behavior) return filter; } const imoFilter = `imo:[${Array.from(imoSet).join(",")}]`; if (filter && filter.trim()) { return `${filter} && ${imoFilter}`; } else { return imoFilter; } } catch (error) { logger.error(`Error updating Typesense filter with company IMOs: ${error}`); return filter; // Return original filter on error } } /** * Get company IMO numbers as array (for backward compatibility) */ async getCompanyImoNumbers(companyName, dbName, mongoUri, collectionName = 'common_group_details') { const imoSet = await this.getCompanyImoSet(companyName, dbName, mongoUri, collectionName); return Array.from(imoSet); } async filterImoListForCompany(imoList, dbName, mongoUri) { const companyName = this.getCompanyName(); // If no company name, return all IMOs if (!companyName) { return imoList; } // Bypass filtering for "Synergy" company if (companyName === "Synergy") { return imoList; } // Bypass filtering for admin companies if (shouldBypassImoFiltering(companyName)) { return imoList; } // Use provided dbName/mongoUri or fallback to cached config values const configValues = this.getDbConfig(); const finalDbName = dbName || configValues.dbName; const finalMongoUri = mongoUri || configValues.mongoUri; if (!finalDbName || !finalMongoUri) { return imoList; } // Fetch company IMO set once (cached if available) const companyImoSet = await this.getCompanyImoSet(companyName, finalDbName, finalMongoUri); // If no company IMOs found, return empty list if (companyImoSet.size === 0) { return []; } // Filter the IMO list using O(1) Set lookups return imoList.filter(imo => companyImoSet.has(String(imo))); } /** * Clear cache (useful for testing or forced refresh) */ clearCache() { this.imoCache.clear(); this.cachedCompanyName = null; this.cachedDbConfig = null; } /** * Close all MongoDB connections (cleanup) */ async closeConnections() { const closePromises = Array.from(this.mongoClients.values()).map(client => client.close()); await Promise.all(closePromises); this.mongoClients.clear(); } } // Singleton instance export const companyFilter = new CompanyFilterManager(); // Export functions for backward compatibility export async function fetchCompanyImoNumbers(companyName, dbName, mongoUri, collectionName = 'common_group_details') { return companyFilter.getCompanyImoNumbers(companyName, dbName, mongoUri, collectionName); } export async function isValidImoForCompany(imo, companyName, dbName, mongoUri) { return companyFilter.isValidImoForCompany(imo, companyName, dbName, mongoUri); } export async function updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri) { return companyFilter.updateTypesenseFilterWithCompanyImos(filter, dbName, mongoUri); } export async function filterImoListForCompany(imoList, dbName, mongoUri) { return companyFilter.filterImoListForCompany(imoList, dbName, mongoUri); } // Export shouldBypassImoFiltering for use in handlers export { shouldBypassImoFiltering }; //# sourceMappingURL=company-filtering.js.map