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
JavaScript
/**
* 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