88 * - Configurable validation rule engine
99 * - Standard and custom rule support
1010 * - Kafka integration for claim routing
11- * - Cosmos DB for rule storage and audit
11+ * - MongoDB for rule storage and audit
1212 * - First-pass rate metrics tracking
1313 */
1414
1515import { Kafka , Producer , Consumer , logLevel } from 'kafkajs' ;
16- import { CosmosClient , Container , Database } from '@azure/cosmos ' ;
16+ import { MongoClient , Db , Collection } from 'mongodb ' ;
1717import { BlobServiceClient , ContainerClient } from '@azure/storage-blob' ;
1818import { DefaultAzureCredential } from '@azure/identity' ;
1919import { v4 as uuidv4 } from 'uuid' ;
@@ -43,10 +43,10 @@ export class ClaimsScrubberService {
4343 private kafka : Kafka | null = null ;
4444 private producer : Producer | null = null ;
4545 private consumer : Consumer | null = null ;
46- private cosmosClient : CosmosClient | null = null ;
47- private database : Database | null = null ;
48- private rulesContainer : Container | null = null ;
49- private auditContainer : Container | null = null ;
46+ private mongoClient : MongoClient | null = null ;
47+ private database : Db | null = null ;
48+ private rulesCollection : Collection | null = null ;
49+ private auditCollection : Collection | null = null ;
5050 private blobServiceClient : BlobServiceClient | null = null ;
5151 private archiveContainer : ContainerClient | null = null ;
5252 private startTime : number ;
@@ -104,14 +104,12 @@ export class ClaimsScrubberService {
104104 } ) ;
105105 }
106106
107- // Initialize Cosmos DB
108- this . cosmosClient = new CosmosClient ( {
109- endpoint : this . config . cosmosDb . endpoint ,
110- aadCredentials : credential ,
111- } ) ;
112- this . database = this . cosmosClient . database ( this . config . cosmosDb . databaseName ) ;
113- this . rulesContainer = this . database . container ( this . config . cosmosDb . rulesContainerName ) ;
114- this . auditContainer = this . database . container ( this . config . cosmosDb . auditContainerName ) ;
107+ // Initialize MongoDB
108+ this . mongoClient = new MongoClient ( this . config . mongoDb . connectionString ) ;
109+ await this . mongoClient . connect ( ) ;
110+ this . database = this . mongoClient . db ( this . config . mongoDb . databaseName ) ;
111+ this . rulesCollection = this . database . collection ( this . config . mongoDb . rulesCollectionName ) ;
112+ this . auditCollection = this . database . collection ( this . config . mongoDb . auditCollectionName ) ;
115113
116114 // Initialize Blob Storage
117115 if ( this . config . storage . connectionString ) {
@@ -127,29 +125,26 @@ export class ClaimsScrubberService {
127125 this . archiveContainer = this . blobServiceClient . getContainerClient ( this . config . storage . containerName ) ;
128126 }
129127
130- // Load custom rules from Cosmos DB
128+ // Load custom rules from MongoDB
131129 await this . loadCustomRules ( ) ;
132130 }
133131
134132 /**
135- * Load custom rules from Cosmos DB
133+ * Load custom rules from MongoDB
136134 */
137135 private async loadCustomRules ( ) : Promise < void > {
138- if ( ! this . rulesContainer ) return ;
136+ if ( ! this . rulesCollection ) return ;
139137
140138 try {
141- const query = {
142- query : 'SELECT * FROM c WHERE c.type = @type AND c.enabled = true' ,
143- parameters : [ { name : '@type' , value : 'custom' } ] ,
144- } ;
145-
146- const { resources } = await this . rulesContainer . items . query < CustomRule > ( query ) . fetchAll ( ) ;
139+ const resources = await this . rulesCollection
140+ . find < CustomRule > ( { type : 'custom' , enabled : true } )
141+ . toArray ( ) ;
147142
148143 for ( const rule of resources ) {
149144 this . ruleEngine . addCustomRule ( rule ) ;
150145 }
151146
152- console . log ( `Loaded ${ resources . length } custom rules from Cosmos DB ` ) ;
147+ console . log ( `Loaded ${ resources . length } custom rules from MongoDB ` ) ;
153148 } catch ( error ) {
154149 console . error ( 'Failed to load custom rules:' , error ) ;
155150 }
@@ -376,18 +371,17 @@ export class ClaimsScrubberService {
376371 }
377372
378373 /**
379- * Audit the validation to Cosmos DB
374+ * Audit the validation to MongoDB
380375 */
381376 private async auditValidation (
382377 claim : X12_837_Claim ,
383378 result : ClaimValidationResult ,
384379 correlationId : string
385380 ) : Promise < void > {
386- if ( ! this . auditContainer ) return ;
381+ if ( ! this . auditCollection ) return ;
387382
388383 try {
389384 const auditRecord = {
390- id : uuidv4 ( ) ,
391385 claimId : claim . claimId ,
392386 claimType : claim . claimType ,
393387 patientControlNumber : claim . claimHeader . patientControlNumber ,
@@ -405,11 +399,11 @@ export class ClaimsScrubberService {
405399 . map ( r => r . editCode ) ,
406400 validationTimeMs : result . totalValidationTimeMs ,
407401 correlationId,
408- timestamp : new Date ( ) . toISOString ( ) ,
409- ttl : 90 * 24 * 60 * 60 , // 90 days TTL
402+ timestamp : new Date ( ) ,
403+ expireAt : new Date ( Date . now ( ) + 90 * 24 * 60 * 60 * 1000 ) , // 90 days TTL
410404 } ;
411405
412- await this . auditContainer . items . create ( auditRecord ) ;
406+ await this . auditCollection . insertOne ( auditRecord ) ;
413407 } catch ( error ) {
414408 console . error ( 'Failed to audit claim' , { claimId : claim . claimId } , error ) ;
415409 }
@@ -419,9 +413,9 @@ export class ClaimsScrubberService {
419413 * Add a custom validation rule
420414 */
421415 async addCustomRule ( rule : CustomRule ) : Promise < void > {
422- // Save to Cosmos DB
423- if ( this . rulesContainer ) {
424- await this . rulesContainer . items . create ( rule ) ;
416+ // Save to MongoDB
417+ if ( this . rulesCollection ) {
418+ await this . rulesCollection . insertOne ( rule ) ;
425419 }
426420
427421 // Add to in-memory rule engine
@@ -448,7 +442,7 @@ export class ClaimsScrubberService {
448442 async getHealth ( ) : Promise < HealthStatus > {
449443 const checks : HealthStatus [ 'checks' ] = {
450444 kafka : await this . checkKafkaHealth ( ) ,
451- cosmosDb : await this . checkCosmosDbHealth ( ) ,
445+ mongoDb : await this . checkMongoDbHealth ( ) ,
452446 storage : await this . checkStorageHealth ( ) ,
453447 ruleEngine : this . checkRuleEngineHealth ( ) ,
454448 } ;
@@ -515,19 +509,19 @@ export class ClaimsScrubberService {
515509 }
516510
517511 /**
518- * Check Cosmos DB health
512+ * Check MongoDB health
519513 */
520- private async checkCosmosDbHealth ( ) : Promise < ComponentHealth > {
514+ private async checkMongoDbHealth ( ) : Promise < ComponentHealth > {
521515 const start = Date . now ( ) ;
522516 try {
523517 if ( ! this . database ) {
524518 return {
525519 status : 'unhealthy' ,
526520 lastCheck : new Date ( ) . toISOString ( ) ,
527- error : 'Cosmos DB client not initialized' ,
521+ error : 'MongoDB client not initialized' ,
528522 } ;
529523 }
530- await this . database . read ( ) ;
524+ await this . database . command ( { ping : 1 } ) ;
531525 return {
532526 status : 'healthy' ,
533527 latencyMs : Date . now ( ) - start ,
@@ -629,6 +623,7 @@ export class ClaimsScrubberService {
629623 async close ( ) : Promise < void > {
630624 if ( this . consumer ) await this . consumer . disconnect ( ) ;
631625 if ( this . producer ) await this . producer . disconnect ( ) ;
626+ if ( this . mongoClient ) await this . mongoClient . close ( ) ;
632627 }
633628}
634629
0 commit comments