/// <summary> /// Create Get Patient details /// </summary> internal MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.RegistrationEvent <MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity> CreateRegistrationEventDetailEx(RegistrationEvent res, List <IResultDetail> details) { var retVal = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.RegistrationEvent <MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity>(); var person = res.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; var custodialDevice = res.FindComponent(HealthServiceRecordSiteRoleType.PlaceOfRecord | HealthServiceRecordSiteRoleType.ResponsibleFor) as RepositoryDevice; var replacement = res.FindAllComponents(HealthServiceRecordSiteRoleType.ReplacementOf); // person if (person == null) { retVal.Subject = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.Subject4 <MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity>() { NullFlavor = NullFlavor.NoInformation } } ; else { retVal.Subject = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.Subject4 <MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity>(CreateRegisteredRoleAlt(person, details)); } // custodial device if (custodialDevice == null) { retVal.Custodian = new MARC.Everest.RMIM.CA.R020403.REPC_MT000007CA.Custodian() { NullFlavor = NullFlavor.NoInformation } } ; else { retVal.Custodian = CreateCustodialDevice(custodialDevice, details); } // Replacement foreach (RegistrationEvent replc in replacement) { retVal.ReplacementOf.Add(new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.ReplacementOf( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.PriorRegistration( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.Subject5( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.PriorRegisteredRole() { Id = CreateII(replc.AlternateIdentifier, details) } ) ) )); } return(retVal); }
/// <summary> /// Create custodial data from either a RepositoryDevice or a HealthcareParticipant /// </summary> private Everest.RMIM.UV.NE2008.MFMI_MT700701UV01.Custodian CreateCustodian(RegistrationEvent registrationEvent, TargetConfiguration configuration) { ISystemConfigurationService sysConfig = this.Context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; var subject = registrationEvent.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; var iiSet = new List <II>(CreateIISet(subject.AlternateIdentifiers)); iiSet.RemoveAll(ii => !configuration.NotificationDomain.Exists(o => o.Domain.Equals(ii.Root))); var oidData = sysConfig.OidRegistrar.FindData(iiSet[0].Root); if (oidData == null) { throw new InvalidOperationException("Cannot find notification settings for " + oidData); } var retVal = new Everest.RMIM.UV.NE2008.MFMI_MT700701UV01.Custodian( new Everest.RMIM.UV.NE2008.COCT_MT090003UV01.AssignedEntity() ); // Device retVal.AssignedEntity.SetAssignedPrincipalChoiceList( new Everest.RMIM.UV.NE2008.COCT_MT090303UV01.Device( SET <II> .CreateSET(new II(oidData.Attributes.Find(o => o.Key == "CustodialDeviceId").Value ?? oidData.Oid)), null, oidData.Attributes.Find(o => o.Key == "CustodialDeviceName").Value ?? oidData.Description ) ); retVal.AssignedEntity.Id = SET <II> .CreateSET(new II(oidData.Oid)); return(retVal); }
/// <summary> /// Enrich the registration event /// </summary> internal void EnrichRegistrationEvent(IDbConnection conn, IDbTransaction tx, RegistrationEvent hsrEvent) { decimal tryDec; ISystemConfigurationService configService = ApplicationContext.ConfigurationService; // Create a query based on the person Person subject = hsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; if (subject.AlternateIdentifiers.Exists(o => o.Domain == configService.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid)) { subject = new Person() { AlternateIdentifiers = new List <DomainIdentifier>(subject.AlternateIdentifiers.FindAll(o => o.Domain == configService.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid)), Status = StatusType.Normal } } ; else if (subject.AlternateIdentifiers.Exists(o => o is AuthorityAssignedDomainIdentifier)) { subject = new Person() { AlternateIdentifiers = new List <DomainIdentifier>(subject.AlternateIdentifiers.FindAll(o => o is AuthorityAssignedDomainIdentifier)), Status = StatusType.Normal } } ; else { subject = new Person() { AlternateIdentifiers = new List <DomainIdentifier>(subject.AlternateIdentifiers), Status = StatusType.Normal } }; QueryEvent query = new QueryEvent(); RegistrationEvent evt = new RegistrationEvent(); query.Add(evt, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); evt.Status = StatusType.Active | StatusType.Obsolete; evt.Add(subject, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); query.Add(new QueryParameters() { MatchingAlgorithm = MatchAlgorithm.Exact, MatchStrength = MatchStrength.Exact }, "FLTR", HealthServiceRecordSiteRoleType.FilterOf, null); var tRecordIds = QueryRecord(query); if (tRecordIds.Length != 1) { throw new MissingPrimaryKeyException(ApplicationContext.LocaleService.GetString("DBCF004")); } else if (tRecordIds[0].Domain != configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid) { throw new MissingPrimaryKeyException(ApplicationContext.LocaleService.GetString("DBCF005")); } tryDec = Decimal.Parse(tRecordIds[0].Identifier); hsrEvent.AlternateIdentifier = tRecordIds[0]; }
/// <summary> /// Validate identifiers /// </summary> internal bool ValidateIdentifiers(RegistrationEvent data, List <IResultDetail> dtls) { Person subject = data.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; //var scoper = subject.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.PlaceOfEntry | SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.InformantTo) as HealthcareParticipant; //var custodian = data.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.PlaceOfRecord | SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.ResponsibleFor); bool isValid = true; //// Validate the root //foreach (var id in subject.AlternateIdentifiers) // if (scoper != null && !scoper.AlternateIdentifiers.Exists(o => o.Domain == id.Domain)) // { // isValid = false; // dtls.Add(new FormalConstraintViolationResultDetail(ResultDetailType.Error, this.m_localeService.GetString("MSGW015"), null, null)); // } // else if (scoper != null && String.IsNullOrEmpty(id.AssigningAuthority)) // id.AssigningAuthority = scoper.LegalName.Parts[0].Value; // else if (String.IsNullOrEmpty(id.AssigningAuthority) && custodian is RepositoryDevice && (custodian as RepositoryDevice).AlternateIdentifier.Domain == id.Domain) // id.AssigningAuthority = (custodian as RepositoryDevice).Name; // else if (String.IsNullOrEmpty(id.AssigningAuthority) && custodian is HealthcareParticipant && (custodian as HealthcareParticipant).AlternateIdentifiers.Exists(o => o.Domain == id.Domain)) // id.AssigningAuthority = (custodian as HealthcareParticipant).LegalName.Parts[0].Value; // Validate we know all identifiers foreach (var id in subject.AlternateIdentifiers) { if (String.IsNullOrEmpty(id.AssigningAuthority)) { dtls.Add(new FormalConstraintViolationResultDetail(ResultDetailType.Error, String.Format(m_localeService.GetString("MSGE06A"), id.Domain), null, null)); isValid = false; } } return(isValid); }
/// <summary> /// Create patient structure for the person suitable for a create /// </summary> private Everest.RMIM.UV.NE2008.MFMI_MT700701UV01.Subject2 <Everest.RMIM.UV.NE2008.PRPA_MT201301UV02.Patient> CreatePatient(RegistrationEvent registrationEvent, TargetConfiguration configuration) { // Get the subject from the list of components var subject = registrationEvent.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; var masking = subject.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.FilterOf) as MaskingIndicator; var providerOrg = subject.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.PlaceOfEntry | SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.InformantTo) as HealthcareParticipant; if (subject == null) // validate { return(null); } var iiSet = new List <II>(CreateIISet(subject.AlternateIdentifiers)); iiSet.RemoveAll(ii => !configuration.NotificationDomain.Exists(o => o.Domain.Equals(ii.Root))); // Construct the return value var retVal = new Everest.RMIM.UV.NE2008.MFMI_MT700701UV01.Subject2 <Everest.RMIM.UV.NE2008.PRPA_MT201301UV02.Patient>( new Everest.RMIM.UV.NE2008.PRPA_MT201301UV02.Patient( new SET <II>(iiSet), CreatePerson(subject, configuration), null )); // Act as a source? // Masking indicator if (masking != null) { retVal.registeredRole.ConfidentialityCode = new SET <CE <string> >(CreateCD <String>(masking.MaskingCode)); } // Provider org var oidData = m_configService.OidRegistrar.FindData(iiSet[0].Root); if (oidData != null) { retVal.registeredRole.ProviderOrganization = new Everest.RMIM.UV.NE2008.COCT_MT150003UV03.Organization() { Id = SET <II> .CreateSET(new II(oidData.Oid)), Name = BAG <ON> .CreateBAG(ON.CreateON(null, new ENXP(oidData.Attributes.Find(o => o.Key == "CustodialOrgName").Value ?? oidData.Description))), ContactParty = new List <Everest.RMIM.UV.NE2008.COCT_MT150003UV03.ContactParty>() { new Everest.RMIM.UV.NE2008.COCT_MT150003UV03.ContactParty() { NullFlavor = NullFlavor.NoInformation } } }; } return(retVal); }
/// <summary> /// Find conflicts using identifiers /// </summary> public IEnumerable <SVC.Core.DataTypes.VersionedDomainIdentifier> FindIdConflicts(RegistrationEvent registration) { var registrationService = this.Context.GetService(typeof(IDataRegistrationService)) as IDataRegistrationService; VersionedDomainIdentifier[] pid = null; // Check if the person exists just via the identifier? // This is important because it is not necessarily a merge but an "update if exists" var subject = registration.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; QueryParameters qp = new QueryParameters() { Confidence = 1.0f, MatchingAlgorithm = MatchAlgorithm.Exact, MatchStrength = MatchStrength.Exact }; var config = this.Context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; List <VersionedDomainIdentifier> conflictIds = new List <VersionedDomainIdentifier>(); foreach (var id in subject.AlternateIdentifiers) { var data = config.OidRegistrar.FindData(id.Domain); if (data == null || !data.Attributes.Exists(a => a.Key == "IsUniqueIdentifier" && Convert.ToBoolean(a.Value))) { continue; } var patientQuery = new QueryEvent(); var registrationEvent = new RegistrationEvent(); patientQuery.Add(registrationEvent, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); patientQuery.Add(qp, "FLT", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.FilterOf, null); registrationEvent.Add(new Person() { AlternateIdentifiers = new List <DomainIdentifier>() { id } }, "SUBJ", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf, null); // Perform the query pid = registrationService.QueryRecord(patientQuery); foreach (var result in pid) { if (!conflictIds.Exists(o => o.Identifier.ToString() == result.Identifier)) { conflictIds.Add(result); } } } return(conflictIds.ToArray()); }
/// <summary> /// Update QRI /// </summary> private void UpdateQRI(RegistrationEvent res, NHapi.Model.V25.Segment.QRI qri) { var subject = res.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; var confidence = subject.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.CommentOn | SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.ComponentOf) as QueryParameters; if (confidence != null) { if (confidence.MatchingAlgorithm == MatchAlgorithm.Soundex) { qri.AlgorithmDescriptor.Identifier.Value = "Soundex"; } else if (confidence.MatchingAlgorithm == MatchAlgorithm.Variant) { qri.AlgorithmDescriptor.Identifier.Value = "Variant"; } if (confidence.MatchingAlgorithm == MatchAlgorithm.Unspecified) // identifier match { qri.GetMatchReasonCode(qri.MatchReasonCodeRepetitionsUsed).Value = "ID"; } else if (confidence.MatchingAlgorithm == MatchAlgorithm.Soundex) // soundex { qri.GetMatchReasonCode(qri.MatchReasonCodeRepetitionsUsed).Value = "NP"; } else if (confidence.MatchingAlgorithm == MatchAlgorithm.Exact) // match { qri.GetMatchReasonCode(qri.MatchReasonCodeRepetitionsUsed).Value = "NA"; } else if (confidence.MatchingAlgorithm == MatchAlgorithm.Variant) // variant { qri.GetMatchReasonCode(qri.MatchReasonCodeRepetitionsUsed).Value = "VAR"; } // Confidence qri.CandidateConfidence.Value = confidence.Confidence.ToString("0.##"); } }
/// <summary> /// Create an instance of the identified entity class from the specified person class /// </summary> internal MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity CreateIdentifiedEntity(RegistrationEvent verified, List <IResultDetail> dtls) { // Get localization service ILocalizationService locale = m_context.GetService(typeof(ILocalizationService)) as ILocalizationService; // Find the major components var person = verified.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; // Verify if (person == null) { dtls.Add(new NotImplementedResultDetail(ResultDetailType.Error, locale.GetString("DBCF0007"), null, null)); return(new MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity() { NullFlavor = NullFlavor.NoInformation }); } var mask = person.FindComponent(HealthServiceRecordSiteRoleType.FilterOf) as MaskingIndicator; // Return value var retVal = new MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.IdentifiedEntity( CreateIISet(person.AlternateIdentifiers, dtls), ConvertStatus(person.Status, dtls), CreateIVL(verified.EffectiveTime, dtls), mask == null ? null : CreateCV <String>(mask.MaskingCode, dtls), CreatePerson(person, dtls), new MARC.Everest.RMIM.CA.R020403.PRPA_MT101102CA.Subject() { NullFlavor = NullFlavor.NotApplicable } ); // Return value return(retVal); }
/// <summary> /// Convert the specified patient record to a registration event /// </summary> internal MARC.Everest.RMIM.UV.NE2008.MFMI_MT700711UV01.RegistrationEvent <MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Patient, object> CreateRegistrationEvent(RegistrationEvent res, List <IResultDetail> details) { // Patient var patient = res.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; if (patient == null) { return new MARC.Everest.RMIM.UV.NE2008.MFMI_MT700711UV01.RegistrationEvent <MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Patient, object>() { NullFlavor = NullFlavor.NoInformation } } ; var scoper = patient.FindComponent(HealthServiceRecordSiteRoleType.PlaceOfEntry | HealthServiceRecordSiteRoleType.InformantTo) as HealthcareParticipant; var queryParameter = patient.FindComponent(HealthServiceRecordSiteRoleType.CommentOn | HealthServiceRecordSiteRoleType.ComponentOf) as QueryParameters; var mask = patient.FindComponent(HealthServiceRecordSiteRoleType.FilterOf) as MaskingIndicator; var myOidData = this.m_configService.OidRegistrar.GetOid("CR_CID"); // Return status var retVal = new MARC.Everest.RMIM.UV.NE2008.MFMI_MT700711UV01.RegistrationEvent <MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Patient, object>( ActStatus.Active, new MARC.Everest.RMIM.UV.NE2008.MFMI_MT700711UV01.Subject2 <MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Patient>( new MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Patient( CreateIISet(patient.AlternateIdentifiers, details), ConvertStatus(patient.Status, details), null, new MARC.Everest.RMIM.UV.NE2008.COCT_MT150003UV03.Organization( SET <II> .CreateSET(new II(myOidData.Oid, null)), null, BAG <ON> .CreateBAG(ON.CreateON(null, new ENXP(myOidData.Attributes.Find(o => o.Key == "CustodialOrgName").Value ?? myOidData.Description))), new MARC.Everest.RMIM.UV.NE2008.COCT_MT150003UV03.ContactParty() { NullFlavor = NullFlavor.NoInformation } ), null ) ) ); // Custodian retVal.Custodian = new MARC.Everest.RMIM.UV.NE2008.MFMI_MT700701UV01.Custodian( new MARC.Everest.RMIM.UV.NE2008.COCT_MT090003UV01.AssignedEntity( SET <II> .CreateSET(new II(this.m_configService.Custodianship.Id.Domain)) ) { RepresentedOrganization = new MARC.Everest.RMIM.UV.NE2008.COCT_MT150003UV03.Organization( SET <II> .CreateSET(new II(this.m_configService.Custodianship.Id.Domain, null)), null, BAG <ON> .CreateBAG(ON.CreateON(null, new ENXP(this.m_configService.Custodianship.Name))), new MARC.Everest.RMIM.UV.NE2008.COCT_MT150003UV03.ContactParty() { NullFlavor = NullFlavor.NoInformation } ) } ); retVal.Subject1.registeredRole.SetPatientEntityChoiceSubject(CreatePersonDetail(patient, details)); // Mask if (mask != null) { retVal.Subject1.registeredRole.ConfidentialityCode = new SET <CE <string> >( CreateCD <String>(mask.MaskingCode, details) ); } if (patient.VipCode != null) { retVal.Subject1.registeredRole.VeryImportantPersonCode = CreateCD <String>(patient.VipCode, details); } // Query observation if (queryParameter != null) { retVal.Subject1.registeredRole.SubjectOf1.Add(new MARC.Everest.RMIM.UV.NE2008.PRPA_MT201310UV02.Subject( new MARC.Everest.RMIM.UV.NE2008.PRPA_MT202310UV02.QueryMatchObservation( new CD <string>(queryParameter.MatchingAlgorithm == MatchAlgorithm.Soundex ? "PHCM" : "PTNM", "2.16.840.1.113883.2.20.5.2"), new INT((int)(queryParameter.Confidence * 100)) ) )); } return(retVal); }
/// <summary> /// Handle duplicates resolved message /// </summary> private IGraphable HandlePatientRegistryDuplicatesResolved(MARC.Everest.Connectors.UnsolicitedDataEventArgs e, MARC.Everest.Connectors.IReceiveResult receivedMessage) { // Setup the lists of details and issues List <IResultDetail> dtls = new List <IResultDetail>(receivedMessage.Details); // System configuration service ISystemConfigurationService configService = Context.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; // Localization service ILocalizationService locale = Context.GetService(typeof(ILocalizationService)) as ILocalizationService; // Data Service IClientRegistryDataService dataSvc = Context.GetService(typeof(IClientRegistryDataService)) as IClientRegistryDataService; // Do basic check and add common validation errors MessageUtil.ValidateTransportWrapperUv(receivedMessage.Structure as IInteraction, configService, dtls); // Check the request is valid var request = receivedMessage.Structure as PRPA_IN201304UV02; if (request == null) { return(null); } // Determine if the received message was interpreted properly bool isValid = MessageUtil.IsValid(receivedMessage); // set the URI if (request.controlActProcess != null) { request.controlActProcess.Code = request.controlActProcess.Code ?? Util.Convert <CD <String> >(PRPA_IN201302UV02.GetTriggerEvent()); } if (request.Receiver.Count > 0) { request.Receiver[0].Telecom = request.Receiver[0].Telecom ?? e.ReceiveEndpoint.ToString(); } // Construct the acknowledgment var response = new MCCI_IN000002UV01( new II(configService.OidRegistrar.GetOid("CR_MSGID").Oid, Guid.NewGuid().ToString()), DateTime.Now, MCCI_IN000002UV01.GetInteractionId(), request.ProcessingCode, request.ProcessingModeCode, MessageUtil.CreateReceiver(request.Sender), MessageUtil.CreateSenderUv(e.ReceiveEndpoint, configService) ); // Create the support classes List <AuditData> audits = new List <AuditData>(); IheAuditUtil dataUtil = new IheAuditUtil() { Context = this.Context }; // Try to execute the record try { // Determine if the message is valid if (!isValid) { throw new MessageValidationException(locale.GetString("MSGE00A"), receivedMessage.Structure); } // Construct the canonical data structure UvComponentUtil cu = new UvComponentUtil() { Context = this.Context }; RegistrationEvent data = cu.CreateComponents(request.controlActProcess, dtls); // Componentization fail? if (data == null || !dataUtil.ValidateIdentifiers(data, dtls)) { throw new MessageValidationException(locale.GetString("MSGE00A"), receivedMessage.Structure); } // Store var result = dataSvc.Merge(data, request.ProcessingCode != ProcessingID.Production ? DataPersistenceMode.Debugging : DataPersistenceMode.Production); if (result == null || result.VersionId == null) { throw new Exception(locale.GetString("DTPE001")); } dtls.AddRange(result.Details); // prepare the delete audit var person = data.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; var replc = person.FindAllComponents(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.ReplacementOf); foreach (PersonRegistrationRef rplc in replc) { audits.Add(dataUtil.CreateAuditData("ITI-44", ActionType.Delete, dtls.Exists(r => r.Type == ResultDetailType.Error) ? OutcomeIndicator.MinorFail : OutcomeIndicator.Success, e, receivedMessage, new List <VersionedDomainIdentifier>() { new VersionedDomainIdentifier() { Domain = rplc.AlternateIdentifiers[0].Domain, Identifier = rplc.AlternateIdentifiers[0].Identifier } }, data.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.AuthorOf) as HealthcareParticipant)); } // Prepare for audit audits.Add(dataUtil.CreateAuditData("ITI-44", ActionType.Update, dtls.Exists(r => r.Type == ResultDetailType.Error) ? OutcomeIndicator.MinorFail : OutcomeIndicator.Success, e, receivedMessage, new List <VersionedDomainIdentifier>() { result.VersionId }, data.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.AuthorOf) as HealthcareParticipant )); // Add ack response.Acknowledgement.Add(new MARC.Everest.RMIM.UV.NE2008.MCCI_MT100200UV01.Acknowledgement( AcknowledgementType.AcceptAcknowledgementCommitAccept, new MARC.Everest.RMIM.UV.NE2008.MCCI_MT100200UV01.TargetMessage(request.Id) )); } catch (Exception ex) { Trace.TraceError(ex.ToString()); // Prepare for audit audits.Add(dataUtil.CreateAuditData("ITI-44", ActionType.Create, OutcomeIndicator.EpicFail, e, receivedMessage, new List <VersionedDomainIdentifier>(), null )); dtls.Add(new ResultDetail(ResultDetailType.Error, ex.Message, ex)); response.Acknowledgement.Add(new MARC.Everest.RMIM.UV.NE2008.MCCI_MT100200UV01.Acknowledgement( AcknowledgementType.AcceptAcknowledgementCommitError, new MARC.Everest.RMIM.UV.NE2008.MCCI_MT100200UV01.TargetMessage(request.Id) )); } finally { IAuditorService auditService = Context.GetService(typeof(IAuditorService)) as IAuditorService; if (auditService != null) { foreach (var aud in audits) { auditService.SendAudit(aud); } } } // Common response parameters response.ProfileId = new SET <II>(MCCI_IN000002UV01.GetProfileId()); response.VersionCode = HL7StandardVersionCode.Version3_Prerelease1; response.AcceptAckCode = AcknowledgementCondition.Never; response.Acknowledgement[0].AcknowledgementDetail.AddRange(MessageUtil.CreateAckDetailsUv(dtls.ToArray())); return(response); }
/// <summary> /// Find conflicts using fuzzy match /// </summary> public IEnumerable <VersionedDomainIdentifier> FindFuzzyConflicts(RegistrationEvent registration) { var registrationService = this.Context.GetService(typeof(IDataRegistrationService)) as IDataRegistrationService; var persistenceService = this.Context.GetService(typeof(IDataPersistenceService)) as IDataPersistenceService; var clientRegistryConfigService = this.Context.GetService(typeof(IClientRegistryConfigurationService)) as IClientRegistryConfigurationService; VersionedDomainIdentifier[] pid = null; var subject = registration.FindComponent(SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.SubjectOf) as Person; QueryParameters qp = new QueryParameters() { Confidence = 1.0f, MatchingAlgorithm = MatchAlgorithm.Exact, MatchStrength = MatchStrength.Exact }; if (subject.Status != StatusType.Active) { return(pid); } var patientQuery = new QueryEvent(); var registrationEvent = new RegistrationEvent(); patientQuery.Add(registrationEvent, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); patientQuery.Add(qp, "FLT", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.FilterOf, null); // Create merge filter for fuzzy match var ssubject = clientRegistryConfigService.CreateMergeFilter(subject); if (ssubject != null) // Minimum criteria was met { registrationEvent.Add(ssubject, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); pid = registrationService.QueryRecord(patientQuery); } else { pid = new VersionedDomainIdentifier[0]; } // Now, look for all with an assigning authority if (pid.Length > 0) { pid = pid.Where(o => !(o.Identifier == registration.Id.ToString() && o.Domain == ApplicationContext.ConfigurationService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid)).ToArray(); // Load each match quickly and ensure that they don't already have a // different identifier from an assigning authority (not CR_CID) provided // in the registration method. For example, if John Smith, Male, 1984-05-22, 123 Main Street West is // registered from system X with ID 102 , and a subsequent registration message for John Smith, Male, 1984-05-22, 123 Main Street West // is received from system X with ID 104, it is pretty much assured they aren't the same person. If however the // latter message came from system Y with ID 104, then the two should be considered a match. ssubject.AlternateIdentifiers = new List <DomainIdentifier>(); List <VersionedDomainIdentifier> exclude = new List <VersionedDomainIdentifier>(); foreach (var altId in subject.AlternateIdentifiers) { if (altId.Domain != ApplicationContext.ConfigurationService.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid) { var oidData = ApplicationContext.ConfigurationService.OidRegistrar.FindData(altId.Domain); if (oidData == null || oidData.Attributes.Find(o => o.Key == "IsUniqueIdentifier").Value == null || Boolean.Parse(oidData.Attributes.Find(o => o.Key == "IsUniqueIdentifier").Value)) { ssubject.AlternateIdentifiers.Add(new DomainIdentifier() { Domain = altId.Domain }); } } } foreach (var p in pid) { var re = persistenceService.GetContainer(p, true) as RegistrationEvent; var pat = re.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; if (pat.Id == subject.Id || pat.Status != StatusType.Active) // same person { exclude.Add(re.AlternateIdentifier); } else if (pat.AlternateIdentifiers.Exists(o => ssubject.AlternateIdentifiers.Exists(r => r.Domain == o.Domain))) { exclude.Add(re.AlternateIdentifier); } } pid = pid.Where(o => !exclude.Exists(i => i.Domain == o.Domain && i.Identifier == o.Identifier)).ToArray(); } return(pid); }
/// <summary> /// Update container /// </summary> public VersionedDomainIdentifier UpdateContainer(System.ComponentModel.IContainer storageData, DataPersistenceMode mode) { if (m_disposed) { throw new ObjectDisposedException("DatabasePersistenceService"); } if (storageData == null) { throw new ArgumentNullException("storageData"); } // Get the persister IComponentPersister persister = GetPersister(storageData.GetType()); ISystemConfigurationService configService = ApplicationContext.ConfigurationService; if (persister != null) { IDbTransaction tx = null; IDbConnection conn = null; try { conn = DatabasePersistenceService.ConnectionManager.GetConnection(); RegistrationEvent hsrEvent = storageData as RegistrationEvent; // Is the record something that we have access to? if (hsrEvent.AlternateIdentifier != null && !hsrEvent.AlternateIdentifier.Domain.Equals(configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid)) { throw new ArgumentException(String.Format("The record OID '{0}' cannot be retrieved by this repository, expecting OID '{1}'", hsrEvent.AlternateIdentifier.Domain, configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid)); } decimal tryDec = default(decimal); bool isDirectUpdate = false; // Is there no event identifier ? if (hsrEvent.AlternateIdentifier != null && !Decimal.TryParse(hsrEvent.AlternateIdentifier.Identifier, out tryDec)) { throw new ArgumentException(String.Format("The identifier '{0}' is not a valid identifier for this repository", hsrEvent.AlternateIdentifier.Identifier)); } else if (hsrEvent.AlternateIdentifier == null) // The alternate identifier is null ... so we need to look up the registration event to version ... interesting.... { this.EnrichRegistrationEvent(conn, tx, hsrEvent); } else { // Get the person name isDirectUpdate = true; // Explicit update } // Validate and duplicate the components that are to be loaded as part of the new version var oldHsrEvent = GetContainer(hsrEvent.AlternateIdentifier, true) as RegistrationEvent; // Get the old container if (oldHsrEvent == null) { throw new MissingPrimaryKeyException(String.Format("Record {1}^^^&{0}&ISO does not exist", hsrEvent.AlternateIdentifier.Domain, hsrEvent.AlternateIdentifier.Identifier)); } PersonPersister cp = new PersonPersister(); // Validate the old record target Person oldRecordTarget = oldHsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person, newRecordTarget = hsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; Person verifyRecordTarget = null; if (!isDirectUpdate) { Trace.TraceInformation("Not Direct update, enriching the Patient Data"); int idCheck = 0; while (verifyRecordTarget == null || idCheck > newRecordTarget.AlternateIdentifiers.Count) { verifyRecordTarget = cp.GetPerson(conn, null, newRecordTarget.AlternateIdentifiers[idCheck++], true); } if (verifyRecordTarget == null || oldRecordTarget.Id != verifyRecordTarget.Id) { throw new ConstraintException("The update request specifies a different subject than the request currently stored"); } } else { verifyRecordTarget = oldRecordTarget; } //newRecordTarget.VersionId = verifyRecordTarget.VersionId; newRecordTarget.Id = verifyRecordTarget.Id; // VAlidate classific if (oldHsrEvent.EventClassifier != hsrEvent.EventClassifier && (hsrEvent.EventClassifier & RegistrationEventType.Register) == RegistrationEventType.None) { throw new ConstraintException("Record type mis-match between update data and the data already in the persistence store"); } if (oldHsrEvent.LanguageCode != hsrEvent.LanguageCode) { throw new ConstraintException("Record language mis-match between update data and data already in persistence store. To change the language use a \"replaces\" relationship rather than an update"); } // Are we performing a component update? If so the only two components we want freshened are the CommentOn (for adding comments) // and the ReasonFor | OlderVersionOf comment for change summaries if ((hsrEvent.EventClassifier & RegistrationEventType.ComponentEvent) != 0) { for (int i = hsrEvent.XmlComponents.Count - 1; i >= 0; i--) { if (((hsrEvent.XmlComponents[i].Site as HealthServiceRecordSite).SiteRoleType & (HealthServiceRecordSiteRoleType.CommentOn | HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf | HealthServiceRecordSiteRoleType.TargetOf)) == 0) { hsrEvent.Remove(hsrEvent.XmlComponents[i]); } } } // Copy over any components that aren't already specified or updated in the new record // Merge the old and new. Sets the update mode appropriately cp.MergePersons(newRecordTarget, oldRecordTarget); // Next we copy this as a replacement of hsrEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf); hsrEvent.Add(newRecordTarget, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); // Begin and update tx = conn.BeginTransaction(); var retVal = persister.Persist(conn, tx, storageData as IComponent, true); if (m_configuration.OverridePersistenceMode.HasValue) { mode = m_configuration.OverridePersistenceMode.Value; } if (mode == DataPersistenceMode.Production) { tx.Commit(); tx = null; // Mark conflicts if any are outstanding pointing at the old versionj if (this.m_clientRegistryMerge != null) { var existingConflicts = this.m_clientRegistryMerge.GetConflicts(oldHsrEvent.AlternateIdentifier); if (existingConflicts.Count() > 0) { Trace.TraceInformation("Obsoleting existing conlflicts resolved"); this.m_clientRegistryMerge.ObsoleteConflicts(oldHsrEvent.AlternateIdentifier); } this.m_threadPool.QueueUserWorkItem(this.MarkConflictsAsync, retVal); } // Notify register if (this.m_notificationService != null) { if (hsrEvent.Mode == RegistrationEventType.Replace) { this.m_notificationService.NotifyDuplicatesResolved(hsrEvent); } else { this.m_notificationService.NotifyUpdate(hsrEvent); } } } else { tx.Rollback(); } return(retVal); } catch (Exception e) { if (tx != null) { tx.Rollback(); } throw; } finally { if (tx != null) { tx.Dispose(); } if (conn != null) { DatabasePersistenceService.ConnectionManager.ReleaseConnection(conn); conn = null; } } } else { Trace.TraceError("Can't find a persistence handler for type '{0}'", storageData.GetType().Name); throw new DataException(String.Format("Can't persist type '{0}'", storageData.GetType().Name)); } }
/// <summary> /// Create the response registration event /// </summary> internal MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.RegistrationEvent <MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdentifiedEntity> CreateRegistrationEventDetail(RegistrationEvent res, List <IResultDetail> details) { var retVal = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.RegistrationEvent <MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdentifiedEntity>(); var person = res.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; var custodialDevice = res.FindComponent(HealthServiceRecordSiteRoleType.PlaceOfRecord | HealthServiceRecordSiteRoleType.ResponsibleFor) as RepositoryDevice; var replacement = res.FindAllComponents(HealthServiceRecordSiteRoleType.ReplacementOf); // person if (person == null) { retVal.Subject = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.Subject4 <MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdentifiedEntity>() { NullFlavor = NullFlavor.NoInformation } } ; else { var regRole = CreateRegisteredRole(person, details); retVal.Subject = new MARC.Everest.RMIM.CA.R020403.MFMI_MT700746CA.Subject4 <MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdentifiedEntity>( new MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdentifiedEntity( regRole.Id, regRole.StatusCode, regRole.EffectiveTime, regRole.ConfidentialityCode, new MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.Person(), regRole.SubjectOf )); if (regRole.IdentifiedPerson != null && regRole.IdentifiedPerson.NullFlavor == null) { foreach (var othId in regRole.IdentifiedPerson.AsOtherIDs) { retVal.Subject.registeredRole.IdentifiedPerson.AsOtherIDs.Add( new MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.OtherIDs( othId.Id, othId.Code, new MARC.Everest.RMIM.CA.R020403.PRPA_MT101106CA.IdOrganization( othId.AssigningIdOrganization.Id, othId.AssigningIdOrganization.Name) )); } } } // custodial device if (custodialDevice == null) { retVal.Custodian = new MARC.Everest.RMIM.CA.R020403.REPC_MT000007CA.Custodian() { NullFlavor = NullFlavor.NoInformation } } ; else { retVal.Custodian = CreateCustodialDevice(custodialDevice, details); } // Replacement foreach (RegistrationEvent replc in replacement) { retVal.ReplacementOf.Add(new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.ReplacementOf( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.PriorRegistration( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.Subject5( new MARC.Everest.RMIM.CA.R020403.MFMI_MT700726CA.PriorRegisteredRole() { Id = CreateII(replc.AlternateIdentifier, details) } ) ) )); } return(retVal); }