/// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 18, separator),
                       PersonIdentifier,
                       FamilyName?.ToDelimitedString(),
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       SourceTable,
                       AssigningAuthority?.ToDelimitedString(),
                       NameTypeCode,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       NameRepresentationCode,
                       NameContext?.ToDelimitedString(),
                       NameValidityRange?.ToDelimitedString(),
                       NameAssemblyOrder
                       ).TrimEnd(separator.ToCharArray()));
        }
        /// <summary>
        /// Converts a <see cref="EditAssigningAuthorityModel"/> instance to an <see cref="AssigningAuthorityInfo"/> instance.
        /// </summary>
        /// <returns>Returns an <see cref="AssigningAuthorityInfo"/> instance.</returns>
        public AssigningAuthority ToAssigningAuthorityInfo(AssigningAuthority authorityInfo)
        {
            authorityInfo.Url             = this.Url;
            authorityInfo.DomainName      = this.DomainName;
            authorityInfo.Description     = this.Description;
            authorityInfo.Oid             = this.Oid;
            authorityInfo.Name            = this.Name;
            authorityInfo.ValidationRegex = this.ValidationRegex;

            if (!this.AddConcepts.Any())
            {
                return(authorityInfo);
            }

            foreach (var concept in AddConcepts)
            {
                Guid id;
                if (Guid.TryParse(concept, out id))
                {
                    if (authorityInfo.AuthorityScopeXml == null)
                    {
                        authorityInfo.AuthorityScopeXml = new List <Guid>();
                    }

                    authorityInfo.AuthorityScopeXml.Add(id);
                }
            }

            return(authorityInfo);
        }
예제 #3
0
        /// <summary>
        /// Converts an <see cref="NHapi.Model.V25.Datatype.HD"/> instance to an <see cref="AssigningAuthority"/> instance.
        /// </summary>
        /// <param name="id">The id value to be converted.</param>
        /// <returns>Returns the converted assigning authority.</returns>
        public static AssigningAuthority ConvertAssigningAuthority(NHapi.Model.V25.Datatype.HD id, List <IResultDetail> details)
        {
            var assigningAuthorityRepositoryService = ApplicationContext.Current.GetAssigningAuthorityService();

            AssigningAuthority assigningAuthority = null;

            if (id == null)
            {
                details.Add(new MandatoryElementMissingResultDetail(ResultDetailType.Error, null, null));
                return(assigningAuthority);
            }

            if (!string.IsNullOrEmpty(id.NamespaceID.Value))
            {
                assigningAuthority = assigningAuthorityRepositoryService.Find(a => a.Name == id.NamespaceID.Value).FirstOrDefault();
            }

            if (!string.IsNullOrEmpty(id.UniversalID.Value))
            {
                assigningAuthority = assigningAuthorityRepositoryService.Find(a => a.Oid == id.UniversalID.Value).FirstOrDefault();
            }

            if (!string.IsNullOrEmpty(id.UniversalIDType.Value) && id.UniversalIDType.Value != "ISO")
            {
                details.Add(new NotImplementedResultDetail(ResultDetailType.Warning, ApplicationContext.Current.GetLocaleString("MSGW016"), null));
            }

            return(assigningAuthority);
        }
예제 #4
0
 /// <summary>
 /// Convert assigning authortiy to v2
 /// </summary>
 public static HD FromModel(this HD me, AssigningAuthority authority)
 {
     me.NamespaceID.Value     = authority.DomainName;
     me.UniversalID.Value     = authority.Oid;
     me.UniversalIDType.Value = !String.IsNullOrEmpty(authority.Oid) ? "ISO" : null;
     return(me);
 }
예제 #5
0
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 16, separator),
                       PersonIdentifier,
                       FamilyName,
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       SourceTable,
                       AssigningAuthority?.ToDelimitedString(),
                       NameTypeCode,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       DateTimeActionPerformed.HasValue ? DateTimeActionPerformed.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       NameRepresentationCode
                       ).TrimEnd(separator.ToCharArray()));
        }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 23, separator),
                       PersonIdentifier,
                       FamilyName?.ToDelimitedString(),
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       SourceTable,
                       AssigningAuthority?.ToDelimitedString(),
                       NameTypeCode,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       NameRepresentationCode,
                       NameContext?.ToDelimitedString(),
                       NameValidityRange?.ToDelimitedString(),
                       NameAssemblyOrder,
                       EffectiveDate.HasValue ? EffectiveDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ExpirationDate.HasValue ? ExpirationDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ProfessionalSuffix,
                       AssigningJurisdiction?.ToDelimitedString(),
                       AssigningAgencyOrDepartment?.ToDelimitedString()
                       ).TrimEnd(separator.ToCharArray()));
        }
예제 #7
0
 public virtual string ToString(char separator)
 {
     return($"{OrganizationName}{separator}{OrganizationNameTypeCode?.BestValue}{separator}{ID}" +
            $"{separator}{CheckDigit}{separator}{CheckDigitScheme?.BestValue}" +
            $"{separator}{AssigningAuthority?.ToString()}{separator}{IdentifierTypeCode?.BestValue}" +
            $"{separator}{AssigningFacility?.ToString()}"
            .TrimEnd(separator));
 }
            public string ToString(char separator)
            {
                var ns = NextSeparator(separator);

                return
                    ($"{ID}{separator}{CheckDigit}{separator}{CheckDigitScheme?.BestValue}{separator}" +
                     $"{AssigningAuthority?.ToString(ns)}{separator}{IdentifierTypeCode?.BestValue}{separator}" +
                     $"{AssigningFacility?.ToString(ns)}{EffectiveDate?.AsDTLocal()}{separator}{ExpirationDate?.AsDTLocal()}"
                     .TrimEnd(separator));
            }
        /// <summary>
        /// Inserts an assigning authority.
        /// </summary>
        /// <param name="assigningAuthority">The assigning authority to be inserted.</param>
        /// <returns>Returns the inserted assigning authority.</returns>
        public AssigningAuthority Insert(AssigningAuthority assigningAuthority)
        {
            var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <AssigningAuthority> >();

            if (persistenceService == null)
            {
                throw new InvalidOperationException($"{nameof(IDataPersistenceService<AssigningAuthority>)} not found");
            }

            return(persistenceService.Insert(assigningAuthority, AuthenticationContext.Current.Principal, TransactionMode.Commit));
        }
예제 #10
0
        /// <summary>
        /// Create the specified authority
        /// </summary>
        public static void CreateAuthority(string nsid, string oid, string url, string applicationName, byte[] deviceSecret)
        {
            // Create the test harness device / application
            var securityDevService = ApplicationServiceContext.Current.GetService <IRepositoryService <SecurityDevice> >();
            var securityAppService = ApplicationServiceContext.Current.GetService <IRepositoryService <SecurityApplication> >();
            var metadataService    = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>();

            using (AuthenticationContext.EnterSystemContext())
            {
                var pubId  = $"{applicationName}|TEST";
                var device = securityDevService.Find(o => o.Name == pubId).FirstOrDefault();
                if (device == null)
                {
                    device = new SecurityDevice
                    {
                        DeviceSecret = BitConverter.ToString(deviceSecret).Replace("-", ""),
                        Name         = $"{applicationName}|TEST"
                    };
                    device.AddPolicy(PermissionPolicyIdentifiers.LoginAsService);
                    device = securityDevService.Insert(device);
                }

                // Application
                var app = securityAppService.Find(o => o.Name == applicationName).FirstOrDefault();
                if (app == null)
                {
                    app = new SecurityApplication
                    {
                        Name = applicationName,
                        ApplicationSecret = BitConverter.ToString(deviceSecret).Replace("-", "")
                    };
                    app.AddPolicy(PermissionPolicyIdentifiers.LoginAsService);
                    app.AddPolicy(PermissionPolicyIdentifiers.UnrestrictedClinicalData);
                    app.AddPolicy(PermissionPolicyIdentifiers.UnrestrictedMetadata);
                    app = securityAppService.Insert(app);
                }

                // Create AA
                var aa = metadataService.Get(nsid);
                if (aa == null)
                {
                    aa = new AssigningAuthority(nsid, nsid, oid)
                    {
                        AssigningApplicationKey = app.Key,
                        IsUnique = true,
                        Url      = url
                    };
                    metadataService.Insert(aa);
                }
            }
        }
예제 #11
0
            public override string ToString(char separator)
            {
                var ns = NextSeparator(separator);

                return
                    ($"{ID}{separator}{FamilyName}{separator}{GivenName}{separator}{SecondGivenNamesOrInitials}" +
                     $"{separator}{Suffix}{separator}{Prefix}{separator}{Degree}{separator}" +
                     $"{SourceTable}{separator}{AssigningAuthority?.ToString(ns)}{separator}" +
                     $"{NameTypeCode}{separator}{IdentifierCheckDigit}{separator}{CheckDigitScheme}{separator}" +
                     $"{IdentifierTypeCode}{separator}{AssigningFacility?.ToString(ns)}{separator}" +
                     $"{NameRepresentationCode}{separator}{NameContext?.ToString(ns)}{separator}" +
                     $"{NameValidityRange?.ToString(ns)}{separator}{NameAssemblyOrder}"
                     .TrimEnd(separator));
            }
예제 #12
0
 /// <summary>
 /// Convert this AA to OID Data for configuration purposes
 /// </summary>
 public static OidData ToOidData(this AssigningAuthority me)
 {
     return(new OidData()
     {
         Name = me.Name,
         Description = me.Description,
         Oid = me.Oid,
         Ref = new Uri(String.IsNullOrEmpty(me.Url) ? String.Format("urn:uuid:{0}", me.Oid) : me.Url),
         Attributes = new System.Collections.Generic.List <System.Collections.Generic.KeyValuePair <string, string> >()
         {
             new System.Collections.Generic.KeyValuePair <string, string>("HL7CX4", me.DomainName)
             //new System.Collections.Generic.KeyValuePair<string, string>("AssigningDevFacility", this.AssigningDevice.DeviceEvidence)
         }
     });
 }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 6, separator),
                       IdNumber,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       AssigningAuthority?.ToDelimitedString(),
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString()
                       ).TrimEnd(separator.ToCharArray()));
        }
예제 #14
0
        /// <summary>
        /// Converts an <see cref="HD"/> instance to an <see cref="AssigningAuthority"/> instance.
        /// </summary>
        /// <param name="id">The id value to be converted.</param>
        /// <returns>Returns the converted assigning authority.</returns>
        public static AssigningAuthority ToModel(this HD id)
        {
            var assigningAuthorityRepositoryService = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>();
            AssigningAuthority assigningAuthority   = null;

            if (id == null)
            {
                throw new ArgumentNullException(nameof(id), "Missing ID parameter");
            }

            // Internal key identifier?
            if (!String.IsNullOrEmpty(id.NamespaceID.Value) && id.NamespaceID.Value == m_configuration.LocalAuthority.DomainName ||
                !String.IsNullOrEmpty(id.UniversalID.Value) && id.UniversalID.Value == m_configuration.LocalAuthority.Oid)
            {
                return(m_configuration.LocalAuthority);
            }

            if (!string.IsNullOrEmpty(id.NamespaceID.Value))
            {
                assigningAuthority = assigningAuthorityRepositoryService.Get(id.NamespaceID.Value);
                if (assigningAuthority == null)
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 1, new KeyNotFoundException($"Authority {id.NamespaceID.Value} not found"));
                }
            }

            if (!string.IsNullOrEmpty(id.UniversalID.Value))
            {
                var tAssigningAuthority = assigningAuthorityRepositoryService.Get(new Uri($"urn:oid:{id.UniversalID.Value}"));

                if (tAssigningAuthority == null)
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 2, new KeyNotFoundException($"Authority {id.UniversalID.Value} not found"));
                }
                else if (assigningAuthority != null && tAssigningAuthority?.Key != assigningAuthority.Key) // Must agree
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 2, new ArgumentException("When both NamespaceID and UniversalID are specified, both must agree with configured values"));
                }
                else
                {
                    assigningAuthority = tAssigningAuthority;
                }
            }

            return(assigningAuthority);
        }
        /// <summary>
        /// Determines whether the identifier is valid for the given assigning authority.
        /// </summary>
        /// <param name="assigningAuthority">The assigning authority.</param>
        /// <param name="value">The value.</param>
        /// <returns><c>true</c> Determines whether the identifier is valid for the given assigning authority; Otherwise, <c>false</c>.</returns>
        private bool IsValidIdentifier(AssigningAuthority assigningAuthority, string value)
        {
            var status = false;

            if (!string.IsNullOrEmpty(assigningAuthority.ValidationRegex) && !string.IsNullOrWhiteSpace(assigningAuthority.ValidationRegex))
            {
                if (new Regex(assigningAuthority.ValidationRegex).IsMatch(value))
                {
                    status = true;
                }
            }
            else
            {
                status = true;
            }

            return(status);
        }
예제 #16
0
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 8, separator),
                       OrganizationName,
                       OrganizationNameTypeCode,
                       IdNumber.HasValue ? IdNumber.Value.ToString(Consts.NumericFormat, culture) : null,
                       IdentifierCheckDigit.HasValue ? IdentifierCheckDigit.Value.ToString(Consts.NumericFormat, culture) : null,
                       CheckDigitScheme,
                       AssigningAuthority?.ToDelimitedString(),
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString()
                       ).TrimEnd(separator.ToCharArray()));
        }
예제 #17
0
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 8, separator),
                       IdNumber,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       AssigningAuthority?.ToDelimitedString(),
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       EffectiveDate.HasValue ? EffectiveDate.Value.ToString(Consts.DateFormatPrecisionDay, culture) : null,
                       ExpirationDate.HasValue ? ExpirationDate.Value.ToString(Consts.DateFormatPrecisionDay, culture) : null
                       ).TrimEnd(separator.ToCharArray()));
        }
        // [PolicyPermission(System.Security.Permissions.SecurityAction.Demand, PolicyId = PermissionPolicyIdentifiers.UnrestrictedMetadata)]
        public static void AddAssigningAuthority(AddAssigningAuthorityParams parms)
        {
            // First, resolve the assigner
            SecurityApplicationInfo assigner = null;

            if (!String.IsNullOrEmpty(parms.Assigner))
            {
                assigner = m_amiClient.GetApplications(o => o.Name == parms.Assigner).CollectionItem.FirstOrDefault() as SecurityApplicationInfo;
                if (assigner == null)
                {
                    throw new KeyNotFoundException("Assigner unknown");
                }
            }

            // Scope
            List <Concept> scope = new List <Concept>();

            if (parms.Scope?.Count > 0)
            {
                foreach (var s in parms.Scope)
                {
                    var scp = m_hdsiClient.Query <Concept>(o => o.Mnemonic == s, 0, 1, false).Item.OfType <Concept>().FirstOrDefault();
                    if (scp == null)
                    {
                        throw new KeyNotFoundException($"Scope {s} unknown");
                    }
                    scope.Add(scp);
                }
            }

            // Construct AA
            foreach (var domainName in parms.Authority)
            {
                var aa = new AssigningAuthority(domainName, parms.Name, parms.Oid)
                {
                    Url                  = parms.Url,
                    AuthorityScope       = scope,
                    AssigningApplication = assigner?.Entity,
                    IsUnique             = parms.Unique
                };
                aa = m_amiClient.CreateAssigningAuthority(aa);
                Console.WriteLine("CREATE AUTHORITY {0} = {1}", aa.DomainName, aa.Key);
            }
        }
예제 #19
0
        /// <summary>
        /// Get order information
        /// </summary>
        public Act GetOrder(Ecom_DocumentReferenceType documentReference, Guid moodConceptKey)
        {
            if (documentReference == null)
            {
                throw new ArgumentNullException("documentReference", "Document reference must be supplied for correlation lookup");
            }
            else if (String.IsNullOrEmpty(documentReference.entityIdentification))
            {
                throw new ArgumentException("Document reference must carry entityIdentification", "documentReference");
            }

            Guid orderId = Guid.Empty;
            Act  retVal  = null;

            if (Guid.TryParse(documentReference.entityIdentification, out orderId))
            {
                retVal = this.m_actRepository.Get(orderId, Guid.Empty);
            }
            if (retVal == null)
            {
                var oidService = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>();
                var gln        = oidService.Get("GLN");
                AssigningAuthority issuingAuthority = null;
                if (documentReference.contentOwner != null)
                {
                    issuingAuthority = oidService.Find(o => o.Oid == $"{gln.Oid}.{documentReference.contentOwner.gln}").FirstOrDefault();
                }
                if (issuingAuthority == null)
                {
                    issuingAuthority = oidService.Get(this.m_configuration.DefaultContentOwnerAssigningAuthority);
                }
                if (issuingAuthority == null)
                {
                    throw new InvalidOperationException("Could not find assigning authority linked with document reference owner. Please specify a default in the configuration");
                }

                int tr = 0;
                retVal = this.m_actRepository.Find(o => o.ClassConceptKey == ActClassKeys.Supply && o.MoodConceptKey == moodConceptKey && o.Identifiers.Any(i => i.Value == documentReference.entityIdentification && i.AuthorityKey == issuingAuthority.Key), 0, 1, out tr).FirstOrDefault();
            }
            return(retVal);
        }
예제 #20
0
 /// <summary>
 /// Creates an assigning authority.
 /// </summary>
 /// <param name="assigningAuthorityInfo">The assigning authority to be created.</param>
 /// <returns>Returns the created assigning authority.</returns>
 public AssigningAuthority CreateAssigningAuthority(AssigningAuthority assigningAuthorityInfo)
 {
     return(this.Client.Post <AssigningAuthority, AssigningAuthority>("AssigningAuthority", assigningAuthorityInfo));
 }
예제 #21
0
        /// <summary>
        /// The issue despactch advice message will insert a new shipped order into the TImR system.
        /// </summary>
        public void IssueDespatchAdvice(DespatchAdviceMessageType advice)
        {
            if (advice == null || advice.despatchAdvice == null)
            {
                this.m_tracer.TraceError("Invalid message sent");
                throw new InvalidOperationException(this.m_localizationService.GetString("error.messaging.gs1.invalidMessage"));
            }

            // TODO: Validate the standard header
            // Loop
            Bundle orderTransaction = new Bundle();

            foreach (var adv in advice.despatchAdvice)
            {
                // Has this already been created?
                Place sourceLocation         = this.m_gs1Util.GetLocation(adv.shipper),
                         destinationLocation = this.m_gs1Util.GetLocation(adv.receiver);
                if (sourceLocation == null)
                {
                    this.m_tracer.TraceError($"Shipper location not found");
                    throw new KeyNotFoundException(this.m_localizationService.FormatString("error.messaging.gs1.locationNotFound", new
                    {
                        param = "Shipper"
                    }));
                }
                else if (destinationLocation == null)
                {
                    this.m_tracer.TraceError($"Shipper location not found");
                    throw new KeyNotFoundException(this.m_localizationService.FormatString("error.messaging.gs1.locationNotFound", new
                    {
                        param = "Receiver"
                    }));
                }
                // Find the original order which this despatch advice is fulfilling
                Act orderRequestAct = null;
                if (adv.orderResponse != null || adv.purchaseOrder != null)
                {
                    orderRequestAct = this.m_gs1Util.GetOrder(adv.orderResponse ?? adv.purchaseOrder, ActMoodKeys.Request);
                    if (orderRequestAct != null) // Orderless despatch!
                    {
                        // If the original order request is not comlete, then complete it
                        orderRequestAct.StatusConceptKey = StatusKeys.Completed;
                        orderTransaction.Add(orderRequestAct);
                    }
                }

                // Find the author of the shipment

                var oidService = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>();
                var gln        = oidService.Get("GLN");
                AssigningAuthority issuingAuthority = null;
                if (adv.despatchAdviceIdentification.contentOwner != null)
                {
                    issuingAuthority = oidService.Find(o => o.Oid == $"{gln.Oid}.{adv.despatchAdviceIdentification.contentOwner.gln}").FirstOrDefault();
                }
                if (issuingAuthority == null)
                {
                    issuingAuthority = oidService.Get(this.m_configuration.DefaultContentOwnerAssigningAuthority);
                }

                if (issuingAuthority == null)
                {
                    this.m_tracer.TraceError("Could not find default issuing authority for advice identification. Please configure a valid OID");
                    throw new KeyNotFoundException(this.m_localizationService.GetString("error.messaging.gs1.issuingAuthority"));
                }
                int tr       = 0;
                var existing = this.m_actRepository.Find(o => o.Identifiers.Any(i => i.AuthorityKey == issuingAuthority.Key && i.Value == adv.despatchAdviceIdentification.entityIdentification), 0, 1, out tr);
                if (existing.Any())
                {
                    this.m_tracer.TraceWarning("Duplicate despatch {0} will be ignored", adv.despatchAdviceIdentification.entityIdentification);
                    continue;
                }

                // Now we want to create a new Supply act which that fulfills the old act
                Act fulfillAct = new Act()
                {
                    CreationTime     = DateTimeOffset.Now,
                    MoodConceptKey   = ActMoodKeys.Eventoccurrence,
                    ClassConceptKey  = ActClassKeys.Supply,
                    StatusConceptKey = StatusKeys.Active,
                    TypeConceptKey   = Guid.Parse("14d69b32-f6c4-4a49-a527-a74893dbcf4a"), // Order
                    ActTime          = adv.despatchInformation.despatchDateTimeSpecified ? adv.despatchInformation.despatchDateTime : DateTime.Now,
                    Extensions       = new List <ActExtension>()
                    {
                        new ActExtension(Gs1ModelExtensions.ActualShipmentDate, typeof(DateExtensionHandler), adv.despatchInformation.actualShipDateTime),
                        new ActExtension(Gs1ModelExtensions.ExpectedDeliveryDate, typeof(DateExtensionHandler), adv.despatchInformation.estimatedDeliveryDateTime)
                    },
                    Tags = new List <ActTag>()
                    {
                        new ActTag("orderNumber", adv.despatchAdviceIdentification.entityIdentification),
                        new ActTag("orderStatus", "shipped"),
                        new ActTag("http://santedb.org/tags/contrib/importedData", "true")
                    },
                    Identifiers = new List <ActIdentifier>()
                    {
                        new ActIdentifier(issuingAuthority, adv.despatchAdviceIdentification.entityIdentification)
                    },
                    Participations = new List <ActParticipation>()
                    {
                        // TODO: Author
                        // TODO: Performer
                        new ActParticipation(ActParticipationKey.Location, sourceLocation.Key),
                        new ActParticipation(ActParticipationKey.Destination, destinationLocation.Key)
                    }
                };
                orderTransaction.Add(fulfillAct);

                // Fullfillment
                if (orderRequestAct != null)
                {
                    fulfillAct.Relationships = new List <ActRelationship>()
                    {
                        new ActRelationship(ActRelationshipTypeKeys.Fulfills, orderRequestAct.Key)
                    }
                }
                ;


                // Now add participations for each material in the despatch
                foreach (var dal in adv.despatchAdviceLogisticUnit)
                {
                    foreach (var line in dal.despatchAdviceLineItem)
                    {
                        if (line.despatchedQuantity.measurementUnitCode != "dose" &&
                            line.despatchedQuantity.measurementUnitCode != "unit")
                        {
                            this.m_tracer.TraceError("Despatched quantity must be reported in units or doses");
                            throw new InvalidOperationException(this.m_localizationService.GetString("error.messaging.gs1.despatchedQuantity"));
                        }
                        var material = this.m_gs1Util.GetManufacturedMaterial(line.transactionalTradeItem, this.m_configuration.AutoCreateMaterials);

                        // Add a participation
                        fulfillAct.Participations.Add(new ActParticipation(ActParticipationKey.Consumable, material.Key)
                        {
                            Quantity = (int)line.despatchedQuantity.Value
                        });
                    }
                }
            }

            // insert transaction
            if (orderTransaction.Item.Count > 0)
            {
                try
                {
                    ApplicationServiceContext.Current.GetService <IRepositoryService <Bundle> >().Insert(orderTransaction);
                }
                catch (Exception e)
                {
                    this.m_tracer.TraceError("Error issuing despatch advice: {0}", e);
                    throw new Exception(this.m_localizationService.FormatString("error.messaging.gs1.errorIssuing", new
                    {
                        param = e.Message
                    }), e);
                }
            }
        }
예제 #22
0
        /// <summary>
        /// Converts an <see cref="HD"/> instance to an <see cref="AssigningAuthority"/> instance.
        /// </summary>
        /// <param name="id">The id value to be converted.</param>
        /// <returns>Returns the converted assigning authority.</returns>
        public static AssigningAuthority ToModel(this HD id)
        {
            var assigningAuthorityRepositoryService = ApplicationServiceContext.Current.GetService <IAssigningAuthorityRepositoryService>();
            AssigningAuthority assigningAuthority   = null;

            if (id == null)
            {
                throw new ArgumentNullException(nameof(id), "Missing ID parameter");
            }

            // Internal key identifier?
            if (!String.IsNullOrEmpty(id.NamespaceID.Value) && id.NamespaceID.Value == m_configuration.LocalAuthority.DomainName ||
                !String.IsNullOrEmpty(id.UniversalID.Value) && id.UniversalID.Value == m_configuration.LocalAuthority.Oid)
            {
                return(m_configuration.LocalAuthority);
            }

            if (!string.IsNullOrEmpty(id.NamespaceID.Value))
            {
                assigningAuthority = assigningAuthorityRepositoryService.Get(id.NamespaceID.Value);
                if (assigningAuthority == null)
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 1, new KeyNotFoundException($"Authority {id.NamespaceID.Value} not found"));
                }
            }

            if (!string.IsNullOrEmpty(id.UniversalID.Value))
            {
                var tAssigningAuthority = assigningAuthorityRepositoryService.Get(new Uri($"urn:oid:{id.UniversalID.Value}"));

                if (tAssigningAuthority == null)
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 2, new KeyNotFoundException($"Authority {id.UniversalID.Value} not found"));
                }
                else if (assigningAuthority != null && tAssigningAuthority?.Key != assigningAuthority.Key) // Must agree
                {
                    throw new HL7DatatypeProcessingException("Error processing HD", 2, new ArgumentException("When both NamespaceID and UniversalID are specified, both must agree with configured values"));
                }
                else
                {
                    assigningAuthority = tAssigningAuthority;
                }
            }

            // Fuzzy lookup based on principal
            if (!m_configuration.StrictAssigningAuthorities && id.NamespaceID.IsEmpty() && id.UniversalID.IsEmpty())
            {
                var claimsPrincipal = AuthenticationContext.Current.Principal as IClaimsPrincipal;
                if (claimsPrincipal == null)
                {
                    throw new HL7DatatypeProcessingException($"Cannot perform application<>identity domain XREF - authentication provider must be claims principal", 4);
                }
                var appPrincipal = claimsPrincipal.Identities.OfType <IApplicationIdentity>().FirstOrDefault();
                if (appPrincipal == null)
                {
                    throw new SecurityException($"Cannot perform application<>identity domain XREF - no application principal present");
                }
                assigningAuthority = assigningAuthorityRepositoryService.Find(o => o.AssigningApplication.Name == appPrincipal.Name, 0, 2, out int tr).FirstOrDefault();
                if (tr > 1)
                {
                    throw new HL7DatatypeProcessingException($"Ambiguous authority - {appPrincipal.Name} auto mapping of sender to authority can only be done if there are 1 authorities - this device has {tr}", 4);
                }
            }
            return(assigningAuthority);
        }
 /// <summary>
 /// Checks of the selected concept is already in the authority scope list
 /// </summary>
 /// <returns>Returns true if the selected concept exists, false if not found</returns>
 public bool HasSelectedAuthorityScope(AssigningAuthority authorityInfo)
 {
     return(AddConcepts.Any() && authorityInfo.AuthorityScope.Any(scope => scope.Key.ToString().Equals(AddConcepts[0])));
 }
예제 #24
0
        /// <summary>
        /// Parse the Next Of Kin Data
        /// </summary>
        public virtual IEnumerable <IdentifiedData> Parse(ISegment segment, IEnumerable <IdentifiedData> context)
        {
            // Cast segment
            var nk1Segment = segment as NK1;
            var fieldNo    = 0;
            // Person persistence service
            var personService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Person> >();

            try
            {
                // Patient to which the parsing belongs
                var patient = context.OfType <Patient>().FirstOrDefault();
                if (patient == null)
                {
                    this.m_tracer.TraceError("NK1 Requires PID segment to be processed");

                    throw new InvalidOperationException(this.m_localizationService.FormatString("error.messaging.hl7.segmentRequirement", new
                    {
                        param  = "NK1",
                        param2 = "PID"
                    }));
                }

                // Next of kin is a person
                Person retVal = new Person()
                {
                    Key = Guid.NewGuid()
                };
                EntityRelationship retValRelation = new EntityRelationship(EntityRelationshipTypeKeys.NextOfKin, retVal.Key)
                {
                    SourceEntityKey = patient.Key
                };
                bool foundByKey = false;

                // Look for existing person
                fieldNo = 33;
                foreach (var id in nk1Segment.GetNextOfKinAssociatedPartySIdentifiers())
                {
                    var idnumber = id.IDNumber.Value;
                    AssigningAuthority authority = null;
                    try
                    {
                        authority = id.AssigningAuthority.ToModel();
                    }
                    catch (Exception e)
                    {
                        throw new HL7ProcessingException(e.Message, "NK1", nk1Segment.SetIDNK1.Value, 33, 3, e);
                    }
                    Guid   idguid = Guid.Empty;
                    int    tr     = 0;
                    Person found  = null;
                    if (authority.Key == this.m_configuration.LocalAuthority.Key)
                    {
                        found = personService.Get(Guid.Parse(id.IDNumber.Value), null, true, AuthenticationContext.SystemPrincipal);
                    }
                    else if (authority?.IsUnique == true)
                    {
                        found = personService.Query(o => o.Identifiers.Any(i => i.Value == idnumber &&
                                                                           i.Authority.Key == authority.Key), 0, 1, out tr, AuthenticationContext.SystemPrincipal).FirstOrDefault();
                    }
                    if (found != null)
                    {
                        retVal     = found;
                        foundByKey = true;
                        // Existing relationship?
                        retValRelation = ApplicationServiceContext.Current.GetService <IDataPersistenceService <EntityRelationship> >().Query(r => r.SourceEntityKey == patient.Key.Value && r.TargetEntityKey == retVal.Key.Value, AuthenticationContext.SystemPrincipal).FirstOrDefault() ?? retValRelation;
                        break;
                    }
                }

                // Relationship type
                fieldNo = 3;
                if (!nk1Segment.Relationship.IsEmpty())
                {
                    retValRelation.RelationshipTypeKey = nk1Segment.Relationship.ToModel(RelationshipCodeSystem)?.Key;
                }

                // Some relationships only allow one person, we should update them
                var existingNokRel = patient.LoadCollection <EntityRelationship>(nameof(Entity.Relationships)).FirstOrDefault(o => o.RelationshipTypeKey == retValRelation.RelationshipTypeKey);
                if (existingNokRel != null)
                {
                    retValRelation = existingNokRel;
                    if (!foundByKey) // We didn't actually resolve anyone by current key so we should try to find them in the DB
                    {
                        retVal = context.FirstOrDefault(o => o.Key == existingNokRel.TargetEntityKey) as Person;
                        // Mother isn't in context, load
                        if (retVal == null)
                        {
                            retVal = personService.Get(existingNokRel.TargetEntityKey.Value, null, true, AuthenticationContext.SystemPrincipal);
                        }
                        if (retVal == null)
                        {
                            this.m_tracer.TraceError("Cannot locate described NOK entity on patient record");
                            throw new InvalidOperationException(this.m_localizationService.GetString("error.messaging.hl7.entityNOK"));
                        }


                        // IF the person is a PATIENT and not a PERSON we will not update them - too dangerous - ignore the NOK entry
                        if (retVal is Patient && !foundByKey)
                        {
                            return(new IdentifiedData[0]);
                        }
                    }
                }

                fieldNo = 2;
                // Names
                if (nk1Segment.NameRepetitionsUsed > 0)
                {
                    foreach (var itm in nk1Segment.GetName())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Names.FirstOrDefault(o => o.NameUseKey == model.NameUseKey);
                        if (existing == null)
                        {
                            retVal.Names.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Address
                fieldNo = 4;
                if (nk1Segment.AddressRepetitionsUsed > 0)
                {
                    foreach (var itm in nk1Segment.GetAddress())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Addresses.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                        if (existing == null)
                        {
                            retVal.Addresses.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Phone numbers
                fieldNo = 5;
                var telecoms = nk1Segment.GetBusinessPhoneNumber().Union(nk1Segment.GetPhoneNumber());
                foreach (var itm in telecoms)
                {
                    var model    = itm.ToModel();
                    var existing = retVal.Telecoms.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                    if (existing == null)
                    {
                        retVal.Telecoms.Add(model);
                    }
                    else
                    {
                        existing.CopyObjectData(model);
                    }
                }

                fieldNo = 15;
                if (!nk1Segment.AdministrativeSex.IsEmpty())
                {
                    retVal.GenderConcept = nk1Segment.AdministrativeSex.ToConcept(AdministrativeGenderCodeSystem);
                }

                // Organization
                fieldNo = 13;
                if (nk1Segment.OrganizationNameNK1RepetitionsUsed > 0)
                {
                    var orgService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Organization> >();
                    foreach (var xon in nk1Segment.GetOrganizationNameNK1())
                    {
                        var id = xon.ToModel();
                        // Lookup the organization scoper
                        if (id != null)
                        {
                            var organization = orgService?.Query(o => o.Identifiers.Any(i => i.Value == id.Value && i.AuthorityKey == id.AuthorityKey), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                            if (organization == null && !this.m_configuration.StrictMetadataMatch)
                            {
                                organization = new Organization()
                                {
                                    Identifiers = new List <EntityIdentifier>()
                                    {
                                        id
                                    },
                                    Names = new List <EntityName>()
                                    {
                                        new EntityName(NameUseKeys.Assigned, xon.OrganizationName.Value)
                                    }
                                };
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Scoper, organization)
                                {
                                    ClassificationKey = RelationshipClassKeys.ContainedObjectLink
                                });
                            }
                            else
                            {
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Scoper, organization));
                            }
                        }
                        else
                        {
                            this.m_tracer.TraceError("XON requires identifier");
                            throw new HL7DatatypeProcessingException(this.m_localizationService.GetString("error.messaging.hl7.requirementXON"), 10, new ArgumentNullException());
                        }
                    }
                }
                // Context role, when the person should be contact
                fieldNo = 7;
                if (!nk1Segment.ContactRole.IsEmpty())
                {
                    var existingConRole = patient.Relationships.FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Contact && retVal.Key == o.TargetEntityKey);
                    if (existingConRole == null)
                    {
                        patient.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Contact, retVal.Key)
                        {
                            RelationshipRole = nk1Segment.ContactRole.ToModel(ContactRoleRelationship, true)
                        });
                    }
                    else
                    {
                        existingConRole.RelationshipRole = nk1Segment.ContactRole.ToModel(ContactRoleRelationship, true);
                    }
                }

                fieldNo = 16;
                if (!nk1Segment.DateTimeOfBirth.IsEmpty())
                {
                    retVal.DateOfBirth          = nk1Segment.DateTimeOfBirth.ToModel();
                    retVal.DateOfBirthPrecision = nk1Segment.DateTimeOfBirth.ToDatePrecision();
                }

                // Citizenship
                fieldNo = 19;
                if (nk1Segment.CitizenshipRepetitionsUsed > 0)
                {
                    foreach (var cit in nk1Segment.GetCitizenship())
                    {
                        var place = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Identifiers.Any(i => i.Value == cit.Identifier.Value && i.Authority.Key == AssigningAuthorityKeys.Iso3166CountryCode), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                        if (place != null)
                        {
                            if (!retVal.Relationships.Any(r => r.RelationshipTypeKey == EntityRelationshipTypeKeys.Citizen && r.TargetEntityKey == place.Key))
                            {
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Citizen, place.Key));
                            }
                        }
                        else
                        {
                            this.m_tracer.TraceError($"Cannot find country with code {cit.Identifier.Value}");
                            throw new KeyNotFoundException(this.m_localizationService.FormatString("error.messaging.hl7.countryCode", new
                            {
                                param = cit.Identifier.Value
                            }));
                        }
                    }
                }

                fieldNo = 20;
                if (!nk1Segment.PrimaryLanguage.IsEmpty())
                {
                    retVal.LanguageCommunication = new List <PersonLanguageCommunication>()
                    {
                        new PersonLanguageCommunication(nk1Segment.PrimaryLanguage.Identifier.Value.ToLower(), true)
                    }
                }
                ;

                // Privacy code
                fieldNo = 23;
                if (!nk1Segment.ProtectionIndicator.IsEmpty())
                {
                    var pip = ApplicationServiceContext.Current.GetService <IDataPersistenceService <SecurityPolicy> >();
                    if (nk1Segment.ProtectionIndicator.Value == "Y")
                    {
                        retVal.AddPolicy(DataPolicyIdentifiers.RestrictedInformation);
                    }
                    else if (nk1Segment.ProtectionIndicator.Value == "N")
                    {
                        retVal.Policies.Clear();
                    }
                    else
                    {
                        this.m_tracer.TraceError($"Protection indicator {nk1Segment.ProtectionIndicator.Value} is invalid");
                        throw new ArgumentOutOfRangeException(this.m_localizationService.FormatString("error.messaging.hl7.protectionInvalid",
                                                                                                      new
                        {
                            param = nk1Segment.ProtectionIndicator.Value
                        }));
                    }
                }

                // Associated person identifiers
                fieldNo = 33;
                if (nk1Segment.NextOfKinAssociatedPartySIdentifiersRepetitionsUsed > 0)
                {
                    retVal.Identifiers.AddRange(nk1Segment.GetNextOfKinAssociatedPartySIdentifiers().ToModel().ToList().Where(i => !retVal.Identifiers.Any(e => e.SemanticEquals(i))));
                }

                // Find the existing relationship on the patient
                if (!patient.Relationships.Any(o => o.RelationshipTypeKey == retValRelation.RelationshipTypeKey && o.TargetEntityKey == retValRelation.TargetEntityKey))
                {
                    patient.Relationships.Add(retValRelation);
                }

                if (!context.Contains(retVal))
                {
                    return new IdentifiedData[] { retVal }
                }
                ;
                else
                {
                    return(new IdentifiedData[0]);
                }
            }
            catch (HL7ProcessingException) // Just re-throw
            {
                throw;
            }
            catch (HL7DatatypeProcessingException e)
            {
                throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException",
                                                                                         new
                {
                    param = "NK1"
                }), "NK1", nk1Segment.SetIDNK1.Value, fieldNo, e.Component, e);
            }
            catch (Exception e)
            {
                throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException",
                                                                                         new
                {
                    param = "NK1"
                }), "NK1", nk1Segment.SetIDNK1.Value, fieldNo, 1, e);
            }
        }
예제 #25
0
        public void TestShouldAdhereToClassifierCodes()
        {
            AssigningAuthority aa = new AssigningAuthority()
            {
                Name       = "Ontario Health Insurance Card",
                DomainName = "OHIPCARD",
                Oid        = "1.2.3.4.5.67"
            };
            var aaPersistence = ApplicationServiceContext.Current.GetService <IDataPersistenceService <AssigningAuthority> >();
            var ohipAuth      = aaPersistence.Insert(aa, TransactionMode.Commit, s_authorization);

            Patient p = new Patient()
            {
                StatusConcept = new Concept()
                {
                    Mnemonic = "ACTIVE"
                },
                Names = new List <EntityName>()
                {
                    new EntityName()
                    {
                        NameUse = new Concept()
                        {
                            Mnemonic = "OfficialRecord"
                        },
                        Component = new List <EntityNameComponent>()
                        {
                            new EntityNameComponent()
                            {
                                ComponentType = new Concept()
                                {
                                    Mnemonic = "Family"
                                },
                                Value = "Johnson"
                            },
                            new EntityNameComponent()
                            {
                                ComponentType = new Concept()
                                {
                                    Mnemonic = "Given"
                                },
                                Value = "William"
                            },
                            new EntityNameComponent()
                            {
                                ComponentType = new Concept()
                                {
                                    Mnemonic = "Given"
                                },
                                Value = "P."
                            },
                            new EntityNameComponent()
                            {
                                ComponentType = new Concept()
                                {
                                    Mnemonic = "Given"
                                },
                                Value = "Bear"
                            }
                        }
                    }
                },
                Identifiers = new List <EntityIdentifier>()
                {
                    new EntityIdentifier(
                        new AssigningAuthority()
                    {
                        DomainName = "OHIPCARD"
                    }, "12343120423")
                },
                Tags = new List <EntityTag>()
                {
                    new EntityTag("hasBirthCertificate", "true")
                },
                Extensions = new List <EntityExtension>()
                {
                    new EntityExtension()
                    {
                        ExtensionType = new ExtensionType()
                        {
                            Name             = "http://santedb.org/oiz/birthcertificate",
                            ExtensionHandler = typeof(EntityPersistenceServiceTest)
                        },
                        ExtensionValueXml = new byte[] { 1 }
                    }
                },
                GenderConcept = new Concept()
                {
                    Mnemonic = "Male"
                },
                DateOfBirth           = new DateTime(1984, 03, 22),
                MultipleBirthOrder    = 2,
                DeceasedDate          = new DateTime(2016, 05, 02),
                DeceasedDatePrecision = DatePrecision.Day,
                DateOfBirthPrecision  = DatePrecision.Day
            };

            var afterInsert = base.DoTestInsert(p, s_authorization);

            Assert.AreEqual("Male", afterInsert.LoadProperty(o => o.GenderConcept).Mnemonic);
            Assert.AreEqual(EntityClassKeys.Patient, p.ClassConceptKey);
            Assert.AreEqual(DeterminerKeys.Specific, p.DeterminerConceptKey);
            Assert.AreEqual(StatusKeys.Active, p.StatusConceptKey);
            //Assert.AreEqual(aa.Key, afterInsert.Identifiers[0].AuthorityKey);
        }
예제 #26
0
        /// <summary>
        /// Parse the Next Of Kin Data
        /// </summary>
        public virtual IEnumerable <IdentifiedData> Parse(ISegment segment, IEnumerable <IdentifiedData> context)
        {
            // Cast segment
            var nk1Segment = segment as NK1;
            var fieldNo    = 0;
            // Person persistence service
            var personService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Person> >();

            try
            {
                // Patient to which the parsing belongs
                var patient = context.OfType <Patient>().FirstOrDefault();
                if (patient == null)
                {
                    throw new InvalidOperationException("NK1 Requires PID segment to be processed");
                }

                // Next of kin is a person
                Person retVal = new Person()
                {
                    Key = Guid.NewGuid()
                };
                EntityRelationship retValRelation = new EntityRelationship(EntityRelationshipTypeKeys.NextOfKin, retVal.Key)
                {
                    SourceEntityKey = patient.Key
                };
                bool foundByKey = false;

                // Look for existing person
                fieldNo = 33;
                foreach (var id in nk1Segment.GetNextOfKinAssociatedPartySIdentifiers())
                {
                    var idnumber = id.IDNumber.Value;
                    AssigningAuthority authority = null;
                    try
                    {
                        authority = id.AssigningAuthority.ToModel();
                    }
                    catch (Exception e)
                    {
                        throw new HL7ProcessingException(e.Message, "NK1", nk1Segment.SetIDNK1.Value, 33, 3, e);
                    }
                    Guid   idguid = Guid.Empty;
                    int    tr     = 0;
                    Person found  = null;
                    if (authority.Key == this.m_configuration.LocalAuthority.Key)
                    {
                        found = personService.Get(Guid.Parse(id.IDNumber.Value), null, true, AuthenticationContext.SystemPrincipal);
                    }
                    else if (authority?.IsUnique == true)
                    {
                        found = personService.Query(o => o.Identifiers.Any(i => i.Value == idnumber &&
                                                                           i.Authority.Key == authority.Key), 0, 1, out tr, AuthenticationContext.SystemPrincipal).FirstOrDefault();
                    }
                    if (found != null)
                    {
                        retVal     = found;
                        foundByKey = true;
                        // Existing relationship?
                        retValRelation = ApplicationServiceContext.Current.GetService <IDataPersistenceService <EntityRelationship> >().Query(r => r.SourceEntityKey == patient.Key.Value && r.TargetEntityKey == retVal.Key.Value, AuthenticationContext.SystemPrincipal).FirstOrDefault() ?? retValRelation;
                        break;
                    }
                }

                // Relationship type
                fieldNo = 3;
                if (!nk1Segment.Relationship.IsEmpty())
                {
                    retValRelation.RelationshipTypeKey = nk1Segment.Relationship.ToModel(RelationshipCodeSystem)?.Key;
                }

                // Some relationships only allow one person, we should update them
                var existingNokRel = patient.LoadCollection <EntityRelationship>(nameof(Entity.Relationships)).FirstOrDefault(o => o.RelationshipTypeKey == retValRelation.RelationshipTypeKey);
                if (existingNokRel != null)
                {
                    retValRelation = existingNokRel;
                    if (!foundByKey) // We didn't actually resolve anyone by current key so we should try to find them in the DB
                    {
                        retVal = context.FirstOrDefault(o => o.Key == existingNokRel.TargetEntityKey) as Person;
                        // Mother isn't in context, load
                        if (retVal == null)
                        {
                            retVal = personService.Get(existingNokRel.TargetEntityKey.Value, null, true, AuthenticationContext.SystemPrincipal);
                        }
                        if (retVal == null)
                        {
                            throw new InvalidOperationException("Cannot locate described NOK entity on patient record");
                        }

                        // IF the person is a PATIENT and not a PERSON we will not update them - too dangerous - ignore the NOK entry
                        if (retVal is Patient && !foundByKey)
                        {
                            return(new IdentifiedData[0]);
                        }
                    }
                }

                fieldNo = 2;
                // Names
                if (nk1Segment.NameRepetitionsUsed > 0)
                {
                    foreach (var itm in nk1Segment.GetName())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Names.FirstOrDefault(o => o.NameUseKey == model.NameUseKey);
                        if (existing == null)
                        {
                            retVal.Names.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Address
                fieldNo = 4;
                if (nk1Segment.AddressRepetitionsUsed > 0)
                {
                    foreach (var itm in nk1Segment.GetAddress())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Addresses.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                        if (existing == null)
                        {
                            retVal.Addresses.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Phone numbers
                fieldNo = 5;
                var telecoms = nk1Segment.GetBusinessPhoneNumber().Union(nk1Segment.GetPhoneNumber());
                foreach (var itm in telecoms)
                {
                    var model    = itm.ToModel();
                    var existing = retVal.Telecoms.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                    if (existing == null)
                    {
                        retVal.Telecoms.Add(model);
                    }
                    else
                    {
                        existing.CopyObjectData(model);
                    }
                }

                // Context role, when the person should be contact
                fieldNo = 7;
                if (!nk1Segment.ContactRole.IsEmpty())
                {
                    var contactExtension = retVal.Extensions.FirstOrDefault(o => o.ExtensionTypeKey == ExtensionTypeKeys.ContactRolesExtension);

                    if (contactExtension == null)
                    {
                        contactExtension = new EntityExtension(ExtensionTypeKeys.ContactRolesExtension, typeof(DictionaryExtensionHandler), new
                        {
                            roles = new[]
                            {
                                new {
                                    patientKey = patient.Key.Value,
                                    contact    = nk1Segment.ContactRole.Identifier.Value
                                }
                            }.ToList()
                        });
                    }
                    else
                    {
                        var existingValue = (contactExtension.ExtensionValue as dynamic);
                        existingValue.roles.Add(new { patientKey = patient.Key.Value, contact = nk1Segment.ContactRole.Identifier.Value });
                    }
                    retVal.Extensions.Add(contactExtension);
                }

                fieldNo = 16;
                if (!nk1Segment.DateTimeOfBirth.IsEmpty())
                {
                    retVal.DateOfBirth          = nk1Segment.DateTimeOfBirth.ToModel();
                    retVal.DateOfBirthPrecision = nk1Segment.DateTimeOfBirth.ToDatePrecision();
                }

                // Citizenship
                fieldNo = 19;
                if (nk1Segment.CitizenshipRepetitionsUsed > 0)
                {
                    foreach (var cit in nk1Segment.GetCitizenship())
                    {
                        var places = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Identifiers.Any(i => i.Value == cit.Identifier.Value && i.Authority.Key == AssigningAuthorityKeys.Iso3166CountryCode), AuthenticationContext.SystemPrincipal);
                        if (places.Count() == 1)
                        {
                            retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Citizen, places.First().Key));
                        }
                    }
                }

                fieldNo = 20;
                if (!nk1Segment.PrimaryLanguage.IsEmpty())
                {
                    retVal.LanguageCommunication = new List <PersonLanguageCommunication>()
                    {
                        new PersonLanguageCommunication(nk1Segment.PrimaryLanguage.Identifier.Value.ToLower(), true)
                    }
                }
                ;

                // Privacy code
                fieldNo = 23;
                if (!nk1Segment.ProtectionIndicator.IsEmpty())
                {
                    var pip = ApplicationServiceContext.Current.GetService <IDataPersistenceService <SecurityPolicy> >();
                    if (nk1Segment.ProtectionIndicator.Value == "Y")
                    {
                        retVal.AddPolicy(DataPolicyIdentifiers.RestrictedInformation);
                    }
                    else if (nk1Segment.ProtectionIndicator.Value == "N")
                    {
                        retVal.Policies.Clear();
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException($"Protection indicator {nk1Segment.ProtectionIndicator.Value} is invalid");
                    }
                }


                // Associated person identifiers
                fieldNo = 33;
                if (nk1Segment.NextOfKinAssociatedPartySIdentifiersRepetitionsUsed > 0)
                {
                    retVal.Identifiers.AddRange(nk1Segment.GetNextOfKinAssociatedPartySIdentifiers().ToModel().ToList().Where(i => !retVal.Identifiers.Any(e => e.SemanticEquals(i))));
                }

                // Find the existing relationship on the patient

                patient.Relationships.RemoveAll(o => o.SourceEntityKey == retValRelation.SourceEntityKey && o.TargetEntityKey == retValRelation.TargetEntityKey);
                patient.Relationships.Add(retValRelation);

                if (!context.Contains(retVal))
                {
                    return new IdentifiedData[] { retVal }
                }
                ;
                else
                {
                    return(new IdentifiedData[0]);
                }
            }
            catch (HL7ProcessingException) // Just re-throw
            {
                throw;
            }
            catch (HL7DatatypeProcessingException e)
            {
                throw new HL7ProcessingException("Error processing NK1 segment", "NK1", nk1Segment.SetIDNK1.Value, fieldNo, e.Component, e);
            }
            catch (Exception e)
            {
                throw new HL7ProcessingException("Error processing NK1 segment", "NK1", nk1Segment.SetIDNK1.Value, fieldNo, 1, e);
            }
        }
예제 #27
0
        /// <summary>
        /// Parse the parse the specified segment into a patient object
        /// </summary>
        /// <param name="segment">The segment to be parsed</param>
        /// <returns>The parsed patient information</returns>
        public virtual IEnumerable <IdentifiedData> Parse(ISegment segment, IEnumerable <IdentifiedData> context)
        {
            var patientService = ApplicationServiceContext.Current.GetService <IRepositoryService <Patient> >();
            var pidSegment     = segment as PID;
            int fieldNo        = 0;

            try
            {
                Patient retVal = new Patient()
                {
                    Key = Guid.NewGuid(), StatusConceptKey = StatusKeys.New
                };
                Person motherEntity = null;
                List <IdentifiedData> retCollection = new List <IdentifiedData>();

                retVal.CreationAct = context.OfType <ControlAct>().FirstOrDefault();

                // Existing patient?
                if (pidSegment.Message.GetStructureName().StartsWith("ADT"))
                {
                    foreach (var id in pidSegment.GetPatientIdentifierList())
                    {
                        var idnumber = id.IDNumber.Value;
                        AssigningAuthority authority;
                        try
                        {
                            authority = id.AssigningAuthority.ToModel();
                        }
                        catch (Exception e)
                        {
                            throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                            {
                                param = "assigning authority"
                            }), "PID", pidSegment.SetIDPID.Value, 3, 4, e);
                        }

                        // Authority not found?
                        if (authority == null)
                        {
                            this.m_tracer.TraceError($"No authority configured for {id.AssigningAuthority.NamespaceID.Value}");
                            throw new HL7ProcessingException(this.m_localizationService.FormatString("error.messaging.hl7.authorityNone", new
                            {
                                param = id.AssigningAuthority.NamespaceID.Value
                            }), "PID", pidSegment.SetIDPID.Value, 3, 4);
                        }

                        Guid    idguid = Guid.Empty;
                        Patient found  = null;
                        if (authority.Key == this.m_configuration.LocalAuthority.Key)
                        {
                            found = patientService.Get(Guid.Parse(id.IDNumber.Value), Guid.Empty);
                        }
                        else if (authority?.IsUnique == true)
                        {
                            found = patientService.Find(o => o.Identifiers.Any(i => i.Authority.Key == authority.Key && i.Value == idnumber)).FirstOrDefault();
                        }

                        if (found != null)
                        {
                            retVal = (Patient)found.Clone();
                            break;
                        }
                    }
                }

                fieldNo = 2;
                if (!pidSegment.PatientID.IsEmpty())
                {
                    retVal.Identifiers.Add(pidSegment.PatientID.ToModel());
                }

                fieldNo = 3;
                if (pidSegment.PatientIdentifierListRepetitionsUsed > 0)
                {
                    var messageIdentifiers = pidSegment.GetPatientIdentifierList().ToModel();

                    if (this.m_configuration.IdentifierReplacementBehavior == IdentifierReplacementMode.AnyInDomain)
                    {
                        retVal.Identifiers.RemoveAll(o => messageIdentifiers.Any(i => i.EffectiveVersionSequenceId.HasValue && i.AuthorityKey == o.AuthorityKey));
                    }

                    // Remove any identifiers matching the value explicitly
                    retVal.Identifiers.RemoveAll(o => messageIdentifiers.Any(i => i.ObsoleteVersionSequenceId.HasValue && i.AuthorityKey == o.AuthorityKey && i.Value == o.Value));

                    // Add any identifiers which we don't have any other identifier domain for
                    retVal.Identifiers.AddRange(messageIdentifiers.Where(o => !o.ObsoleteVersionSequenceId.HasValue && !retVal.Identifiers.Any(i => i.AuthorityKey == o.AuthorityKey && i.Value == o.Value)));
                }

                // Find the key for the patient
                var keyId = pidSegment.GetPatientIdentifierList().FirstOrDefault(o => o.AssigningAuthority.NamespaceID.Value == this.m_configuration.LocalAuthority.DomainName);
                if (keyId != null)
                {
                    retVal.Key = Guid.Parse(keyId.IDNumber.Value);
                }

                if (!retVal.Identifiers.Any())
                {
                    throw new HL7ProcessingException(this.m_localizationService.GetString("error.messaging.hl7.identityPatient"), "PID", pidSegment.SetIDPID.Value, 3, 1);
                }

                fieldNo = 5;
                if (pidSegment.PatientNameRepetitionsUsed > 0)
                {
                    foreach (var itm in pidSegment.GetPatientName())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Names.FirstOrDefault(o => o.NameUseKey == model.NameUseKey);
                        if (existing == null)
                        {
                            retVal.Names.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                fieldNo = 21;
                // Mother's maiden name, create a relationship for mother
                if (pidSegment.MotherSMaidenNameRepetitionsUsed > 0 || pidSegment.GetMotherSIdentifier().Any(o => !o.IsEmpty()))
                {
                    var    personService  = ApplicationServiceContext.Current.GetService <IRepositoryService <Person> >();
                    Person existingMother = retVal.Relationships.FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Mother)?.LoadProperty(o => o.TargetEntity).GetMaster() as Person;
                    Person foundMother    = null;

                    // Attempt to find the existing mother in the database based on ID
                    foreach (var id in pidSegment.GetMotherSIdentifier().Where(o => !o.IsEmpty()))
                    {
                        AssigningAuthority authority = null;
                        try
                        {
                            authority = id.AssigningAuthority.ToModel();
                        }
                        catch (Exception e)
                        {
                            throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException", new
                            {
                                param = "mother's identifiers"
                            }), "PID", pidSegment.SetIDPID.Value, 21, 3);
                        }

                        if ((authority.Key == this.m_configuration.LocalAuthority.Key || authority.DomainName == this.m_configuration.LocalAuthority.DomainName) && Guid.TryParse(id.IDNumber.Value, out Guid idNumberUuid))
                        {
                            foundMother = personService.Get(idNumberUuid) ?? patientService.Get(idNumberUuid);
                        }
                        else if (authority?.IsUnique == true)
                        {
                            foundMother = personService.Find(o => o.Identifiers.Any(i => i.Value == id.IDNumber.Value && i.Authority.Key == authority.Key)).FirstOrDefault() ??
                                          patientService.Find(o => o.Identifiers.Any(i => i.Value == id.IDNumber.Value && i.Authority.Key == authority.Key)).FirstOrDefault();
                        }

                        if (foundMother != null)
                        {
                            break;
                        }
                    }

                    fieldNo = 6;
                    // Mother doesn't exist and there's no mother currently, so add it
                    if (foundMother == null && existingMother == null)
                    {
                        motherEntity = new Person()
                        {
                            Key              = Guid.NewGuid(),
                            Identifiers      = pidSegment.GetMotherSIdentifier().ToModel().ToList(),
                            Names            = pidSegment.GetMotherSMaidenName().ToModel(NameUseKeys.MaidenName).ToList(),
                            StatusConceptKey = StatusKeys.New
                        };
                        retCollection.Add(motherEntity);
                    }
                    else if (existingMother != null)                                  // existing mother - update
                    {
                        if (!existingMother.LoadCollection(o => o.Identifiers).Any()) // update identifiers
                        {
                            existingMother.Identifiers = pidSegment.GetMotherSIdentifier().ToModel().ToList();
                        }
                        motherEntity = existingMother;
                        retCollection.Add(motherEntity);
                    }
                    else
                    {
                        motherEntity = foundMother;
                    }

                    var existingRelationship = retVal.Relationships.FirstOrDefault(r => r.SourceEntityKey == retVal.Key && r.RelationshipTypeKey == EntityRelationshipTypeKeys.Mother);
                    if (existingRelationship == null)
                    {
                        retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Mother, motherEntity.Key));
                    }
                    else if (existingRelationship.TargetEntityKey != motherEntity.Key)
                    {
                        // Was the mother found?

                        existingRelationship.BatchOperation = BatchOperationType.Delete;
                        retCollection.Add(existingRelationship);
                        retVal.Relationships.Remove(existingRelationship);
                        retCollection.Add(new EntityRelationship(EntityRelationshipTypeKeys.Mother, motherEntity.Key)
                        {
                            SourceEntityKey = retVal.Key
                        });
                    }
                }

                // Nationality
                fieldNo = 28;
                if (!pidSegment.Nationality.IsEmpty())
                {
                    retVal.Nationality = pidSegment.Nationality.ToModel();
                }

                // Date/time of birth
                fieldNo = 7;
                if (!pidSegment.DateTimeOfBirth.IsEmpty())
                {
                    retVal.DateOfBirth          = pidSegment.DateTimeOfBirth.ToModel();
                    retVal.DateOfBirthPrecision = pidSegment.DateTimeOfBirth.ToDatePrecision();
                }

                // Administrative gender
                fieldNo = 8;
                if (!pidSegment.AdministrativeSex.IsEmpty())
                {
                    retVal.GenderConcept = pidSegment.AdministrativeSex.ToConcept(AdministrativeGenderCodeSystem);
                }

                // Patient Alias
                fieldNo = 9;
                if (pidSegment.PatientAliasRepetitionsUsed > 0)
                {
                    retVal.Names.AddRange(pidSegment.GetPatientAlias().ToModel());
                }

                // Race codes
                fieldNo = 10;
                if (pidSegment.RaceRepetitionsUsed > 0)
                {
                    retVal.Extensions.AddRange(pidSegment.GetRace().Select(o => new EntityExtension(ExtensionTypeKeys.PatientRaceExtension, typeof(ReferenceExtensionHandler), o.ToModel(RaceCodeSystem))));
                }

                // Addresses
                fieldNo = 11;
                if (pidSegment.PatientAddressRepetitionsUsed > 0)
                {
                    foreach (var itm in pidSegment.GetPatientAddress())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Addresses.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                        if (existing == null)
                        {
                            retVal.Addresses.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Fields
                fieldNo = 13;
                var telecoms = pidSegment.GetPhoneNumberBusiness().Union(pidSegment.GetPhoneNumberHome());
                foreach (var itm in telecoms)
                {
                    var model    = itm.ToModel();
                    var existing = retVal.Telecoms.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                    if (existing == null)
                    {
                        retVal.Telecoms.Add(model);
                    }
                    else
                    {
                        existing.CopyObjectData(model);
                    }
                }

                // Language
                if (!pidSegment.PrimaryLanguage.IsEmpty())
                {
                    retVal.LanguageCommunication = new List <PersonLanguageCommunication>()
                    {
                        new PersonLanguageCommunication(pidSegment.PrimaryLanguage.Identifier.Value.ToLower(), true)
                    }
                }
                ;

                // Marital Status
                fieldNo = 16;
                if (!pidSegment.MaritalStatus.IsEmpty())
                {
                    retVal.MaritalStatus = pidSegment.MaritalStatus.ToModel(MaritalStatusCodeSystem);
                }

                // Religion
                fieldNo = 17;
                if (!pidSegment.Religion.IsEmpty())
                {
                    retVal.ReligiousAffiliation = pidSegment.Religion.ToModel(ReligionCodeSystem);
                }

                // Ethinic groups
                fieldNo = 22;
                if (pidSegment.EthnicGroupRepetitionsUsed > 0)
                {
                    retVal.EthnicGroupCodeKey = pidSegment.GetEthnicGroup().First().ToModel(EthnicGroupCodeSystem).Key;
                }

                fieldNo = 18;
                // Patient account, locate the specified account
                if (!pidSegment.PatientAccountNumber.IsEmpty())
                {
                    var account = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Account> >()?.Query(o => o.Identifiers.Any(i => i.Value == pidSegment.PatientAccountNumber.IDNumber.Value), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                    if (account != null)
                    {
                        retVal.Participations.Add(new ActParticipation(ActParticipationKey.Holder, retVal)
                        {
                            SourceEntityKey = account.Key
                        });
                    }
                    else
                    {
                        retVal.Participations.Add(new ActParticipation(ActParticipationKey.Holder, retVal)
                        {
                            SourceEntity = new Account()
                            {
                                Identifiers = new List <ActIdentifier>()
                                {
                                    new ActIdentifier()
                                    {
                                        Authority = pidSegment.PatientAccountNumber.AssigningAuthority.ToModel(),
                                        Value     = pidSegment.PatientAccountNumber.IDNumber.Value
                                    }
                                },
                                StatusConceptKey = StatusKeys.New
                            }
                        });
                    }
                }

                // SSN
                fieldNo = 19;

                // Patient account, locate the specified account
                if (!String.IsNullOrEmpty(pidSegment.SSNNumberPatient.Value))
                {
                    var ssn = pidSegment.SSNNumberPatient.Value;
                    // Lookup identity domain which is designated as SSN , if they already have one update it, if not, add it
                    var existing = retVal.Identifiers.FirstOrDefault(o => o.AuthorityKey == this.m_configuration.SsnAuthority.Key || o.LoadProperty(x => x.AuthorityXml).DomainName == this.m_configuration.SsnAuthority?.DomainName);
                    if (existing == null)
                    {
                        retVal.Identifiers.Add(new EntityIdentifier(this.m_configuration.SsnAuthority, ssn));
                    }
                    else
                    {
                        existing.Value = ssn;
                    }
                }

                // Birth place is present
                fieldNo = 23;
                if (!pidSegment.BirthPlace.IsEmpty()) // We need to find the birthplace relationship
                {
                    var existing = retVal.LoadProperty(o => o.Relationships).FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Birthplace);

                    if (Guid.TryParse(pidSegment.BirthPlace.Value, out Guid birthPlaceId))
                    {
                        if (existing == null)
                        {
                            retVal.LoadProperty(o => o.Relationships).Add(new EntityRelationship(EntityRelationshipTypeKeys.Birthplace, birthPlaceId));
                        }
                        else
                        {
                            existing.TargetEntityKey = birthPlaceId;
                        }
                    }
                    else
                    {
                        var places = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Names.Any(n => n.Component.Any(c => c.Value == pidSegment.BirthPlace.Value)), AuthenticationContext.SystemPrincipal);
                        if (this.m_configuration.BirthplaceClassKeys.Any())
                        {
                            places = places.Where(o =>
                                                  this.m_configuration.BirthplaceClassKeys.Contains(o.ClassConceptKey.Value));
                        }

                        // Still conflicts? Check for same region as address
                        if (places.Count() > 1 && !this.m_configuration.StrictMetadataMatch)
                        {
                            var placeClasses = places.GroupBy(o => o.ClassConceptKey).OrderBy(o => Array.IndexOf(AddressHierarchy, o.Key.Value));
                            // Take the first wrung of the address hierarchy
                            places = placeClasses.First();
                            if (places.Count() > 1) // Still more than one type of place
                            {
                                places = places.Where(p => p.LoadCollection <EntityAddress>(nameof(Entity.Addresses)).Any(a => a.Component.All(a2 => retVal.LoadCollection <EntityAddress>(nameof(Entity.Addresses)).Any(pa => pa.Component.Any(pc => pc.Value == a2.Value && pc.ComponentTypeKey == a2.ComponentTypeKey)))));
                            }
                        }

                        // Assign if only one place
                        if (places.Count() == 1)
                        {
                            if (existing == null)
                            {
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Birthplace, places.First().Key));
                            }
                            else
                            {
                                existing.TargetEntityKey = places.First().Key;
                            }
                        }
                        else
                        {
                            throw new KeyNotFoundException(this.m_localizationService.FormatString("error.messaging.hl7.birthPlace", new
                            {
                                param  = pidSegment.BirthPlace.Value,
                                param2 = places.Count()
                            }));
                        }
                    }
                }

                // MB indicator
                if (!pidSegment.MultipleBirthIndicator.IsEmpty())
                {
                    retVal.MultipleBirthOrder = pidSegment.MultipleBirthIndicator.Value == "Y" ? (int?)-1 : null;
                }
                if (!pidSegment.BirthOrder.IsEmpty())
                {
                    retVal.MultipleBirthOrder = Int32.Parse(pidSegment.BirthOrder.Value);
                }

                // Citizenship
                fieldNo = 26;
                if (pidSegment.CitizenshipRepetitionsUsed > 0)
                {
                    foreach (var cit in pidSegment.GetCitizenship())
                    {
                        var place = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Identifiers.Any(i => i.Value == cit.Identifier.Value && i.Authority.Key == AssigningAuthorityKeys.Iso3166CountryCode), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                        if (place != null)
                        {
                            if (!retVal.Relationships.Any(r => r.RelationshipTypeKey == EntityRelationshipTypeKeys.Citizen && r.TargetEntityKey == place.Key))
                            {
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Citizen, place.Key));
                            }
                        }
                        else
                        {
                            m_tracer.TraceError($"Cannot find country with code {cit.Identifier.Value}");
                            throw new KeyNotFoundException(this.m_localizationService.FormatString("error.messaging.hl7.countryCode", new
                            {
                                param = cit.Identifier.Value
                            }));
                        }
                    }
                }

                // Death info
                fieldNo = 29;
                if (!pidSegment.PatientDeathIndicator.IsEmpty())
                {
                    retVal.DeceasedDate = pidSegment.PatientDeathIndicator.Value == "Y" ? (DateTime?)DateTime.MinValue : null;
                }
                if (!pidSegment.PatientDeathDateAndTime.IsEmpty())
                {
                    retVal.DeceasedDate          = pidSegment.PatientDeathDateAndTime.ToModel();
                    retVal.DeceasedDatePrecision = pidSegment.PatientDeathDateAndTime.ToDatePrecision();
                }

                // Last update time
                if (!pidSegment.LastUpdateDateTime.IsEmpty())
                {
                    retVal.CreationTime = (DateTimeOffset)pidSegment.LastUpdateDateTime.ToModel();
                }

                //if(!pidSegment.LastUpdateFacility.IsEmpty())
                //{
                //    // Find by user ID
                //    var user = ApplicationServiceContext.Current.GetService<IDataPersistenceService<SecurityUser>>().Query(u=>u.UserName == pidSegment.LastUpdateFacility.NamespaceID.Value).FirstOrDefault();
                //    if (user != null)
                //        retVal.CreatedBy = user;
                //}

                retVal.AddTag(Hl7Constants.FocalObjectTag, "true");
                retCollection.Add(retVal);

                return(retCollection);
            }
            catch (HL7ProcessingException e) // Just re-throw
            {
                throw;
            }
            catch (HL7DatatypeProcessingException e)
            {
                throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException",
                                                                                         new
                {
                    param = "PID"
                }), "PID", pidSegment.SetIDPID.Value, fieldNo, e.Component, e);
            }
            catch (Exception e)
            {
                throw new HL7ProcessingException(this.m_localizationService.FormatString("error.type.HL7ProcessingException",
                                                                                         new
                {
                    param = "PID"
                }), "PID", pidSegment.SetIDPID.Value, fieldNo, 1, e);
            }
        }
예제 #28
0
        /// <summary>
        /// Parse the parse the specified segment into a patient object
        /// </summary>
        /// <param name="segment">The segment to be parsed</param>
        /// <returns>The parsed patient information</returns>
        public virtual IEnumerable <IdentifiedData> Parse(ISegment segment, IEnumerable <IdentifiedData> context)
        {
            var patientService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Patient> >();
            var personService  = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Person> >();
            var pidSegment     = segment as PID;
            int fieldNo        = 0;

            try
            {
                Patient retVal = new Patient()
                {
                    Key = Guid.NewGuid()
                };
                Person motherEntity = null;
                List <IdentifiedData> retCollection = new List <IdentifiedData>();

                retVal.CreationAct = context.OfType <ControlAct>().FirstOrDefault();

                // Existing patient?
                if (pidSegment.Message.GetStructureName().StartsWith("ADT"))
                {
                    foreach (var id in pidSegment.GetPatientIdentifierList())
                    {
                        var idnumber = id.IDNumber.Value;
                        AssigningAuthority authority;
                        try
                        {
                            authority = id.AssigningAuthority.ToModel();
                        }
                        catch (Exception e)
                        {
                            throw new HL7ProcessingException("Error processig assigning authority", "PID", pidSegment.SetIDPID.Value, 3, 4, e);
                        }

                        if (authority == null)
                        {
                            throw new HL7ProcessingException($"No authority configured for {id.AssigningAuthority.NamespaceID.Value}", "PID", pidSegment.SetIDPID.Value, 3, 4);
                        }
                        Guid   idguid = Guid.Empty;
                        Person found  = null;
                        if (authority.Key == this.m_configuration.LocalAuthority.Key)
                        {
                            found = personService.Get(Guid.Parse(id.IDNumber.Value), null, true, AuthenticationContext.Current.Principal);
                        }
                        else if (authority?.IsUnique == true)
                        {
                            found = personService.Query(o => o.Identifiers.Any(i => i.Authority.Key == authority.Key && i.Value == idnumber), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                        }

                        if (found != null)
                        {
                            if (found is Patient)
                            {
                                retVal = (Patient)found;
                            }
                            else // We need to upgrade this person
                            {
                                retVal.CopyObjectData(found, false, true);
                                retVal.Tags.Add(new EntityTag("$sys.reclass", "true"));
                            }
                            break;
                        }
                    }
                }


                fieldNo = 2;
                if (!pidSegment.PatientID.IsEmpty())
                {
                    retVal.Identifiers.Add(pidSegment.PatientID.ToModel());
                }


                fieldNo = 3;
                if (pidSegment.PatientIdentifierListRepetitionsUsed > 0)
                {
                    retVal.Identifiers.AddRange(
                        pidSegment.GetPatientIdentifierList().ToModel().Where(o => !retVal.Identifiers.Any(i => i.Authority.Key == o.AuthorityKey && i.Value == o.Value)).ToArray()
                        );
                }

                // Find the key for the patient
                var keyId = pidSegment.GetPatientIdentifierList().FirstOrDefault(o => o.AssigningAuthority.NamespaceID.Value == this.m_configuration.LocalAuthority.DomainName);
                if (keyId != null)
                {
                    retVal.Key = Guid.Parse(keyId.IDNumber.Value);
                }

                if (retVal.Identifiers.Count == 0)
                {
                    throw new HL7ProcessingException("Couldn't understand any patient identity", "PID", pidSegment.SetIDPID.Value, 3, 1);
                }

                fieldNo = 5;
                if (pidSegment.PatientNameRepetitionsUsed > 0)
                {
                    foreach (var itm in pidSegment.GetPatientName())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Names.FirstOrDefault(o => o.NameUseKey == model.NameUseKey);
                        if (existing == null)
                        {
                            retVal.Names.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                fieldNo = 21;
                // Mother's maiden name, create a relationship for mother
                if (pidSegment.MotherSMaidenNameRepetitionsUsed > 0 || pidSegment.MotherSIdentifierRepetitionsUsed > 0)
                {
                    // Attempt to find the mother
                    foreach (var id in pidSegment.GetMotherSIdentifier())
                    {
                        AssigningAuthority authority = null;
                        try
                        {
                            authority = id.AssigningAuthority.ToModel();
                        }
                        catch (Exception e)
                        {
                            throw new HL7ProcessingException("Error processing mother's identifiers", "PID", pidSegment.SetIDPID.Value, 21, 3);
                        }

                        if (authority.Key == this.m_configuration.LocalAuthority.Key)
                        {
                            motherEntity = personService.Get(Guid.Parse(id.IDNumber.Value), null, true, AuthenticationContext.SystemPrincipal);
                        }
                        else if (authority?.IsUnique == true)
                        {
                            motherEntity = personService.Query(o => o.Identifiers.Any(i => i.Value == id.IDNumber.Value && i.Authority.Key == authority.Key), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                        }
                    }

                    fieldNo = 6;
                    // Mother doesn't exist, so add it
                    if (motherEntity == null)
                    {
                        motherEntity = new Person()
                        {
                            Key              = Guid.NewGuid(),
                            Identifiers      = pidSegment.GetMotherSIdentifier().ToModel().ToList(),
                            Names            = pidSegment.GetMotherSMaidenName().ToModel(NameUseKeys.MaidenName).ToList(),
                            StatusConceptKey = StatusKeys.New
                        }
                    }
                    ;

                    var existingRelationship = retVal.Relationships.FirstOrDefault(r => r.SourceEntityKey == retVal.Key && r.TargetEntityKey == motherEntity.Key);
                    if (existingRelationship == null)
                    {
                        // Find by mother relationship
                        existingRelationship = retVal.Relationships.FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Mother);
                        if (existingRelationship == null) // No current mother relationship
                        {
                            retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Mother, motherEntity.Key));
                        }
                        else if (!existingRelationship.LoadProperty <Entity>("TargetEntity").SemanticEquals(motherEntity))
                        {
                            existingRelationship.TargetEntityKey = motherEntity.Key;
                        }
                    }
                    else
                    {
                        existingRelationship.RelationshipTypeKey = EntityRelationshipTypeKeys.Mother;
                    }
                }

                // Date/time of birth
                fieldNo = 7;
                if (!pidSegment.DateTimeOfBirth.IsEmpty())
                {
                    retVal.DateOfBirth          = pidSegment.DateTimeOfBirth.ToModel();
                    retVal.DateOfBirthPrecision = pidSegment.DateTimeOfBirth.ToDatePrecision();
                }

                // Administrative gender
                fieldNo = 8;
                if (!pidSegment.AdministrativeSex.IsEmpty())
                {
                    retVal.GenderConcept = pidSegment.AdministrativeSex.ToConcept(AdministrativeGenderCodeSystem);
                }

                // Patient Alias
                fieldNo = 9;
                if (pidSegment.PatientAliasRepetitionsUsed > 0)
                {
                    retVal.Names.AddRange(pidSegment.GetPatientAlias().ToModel());
                }

                // Race codes
                fieldNo = 10;
                if (pidSegment.RaceRepetitionsUsed > 0)
                {
                    ; // TODO: Implement as an extension if needed
                }
                // Addresses
                fieldNo = 11;
                if (pidSegment.PatientAddressRepetitionsUsed > 0)
                {
                    foreach (var itm in pidSegment.GetPatientAddress())
                    {
                        var model    = itm.ToModel();
                        var existing = retVal.Addresses.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                        if (existing == null)
                        {
                            retVal.Addresses.Add(model);
                        }
                        else
                        {
                            existing.CopyObjectData(model);
                        }
                    }
                }

                // Fields
                fieldNo = 13;
                var telecoms = pidSegment.GetPhoneNumberBusiness().Union(pidSegment.GetPhoneNumberHome());
                foreach (var itm in telecoms)
                {
                    var model    = itm.ToModel();
                    var existing = retVal.Telecoms.FirstOrDefault(o => o.AddressUseKey == model.AddressUseKey);
                    if (existing == null)
                    {
                        retVal.Telecoms.Add(model);
                    }
                    else
                    {
                        existing.CopyObjectData(model);
                    }
                }

                // Language
                if (!pidSegment.PrimaryLanguage.IsEmpty())
                {
                    retVal.LanguageCommunication = new List <PersonLanguageCommunication>()
                    {
                        new PersonLanguageCommunication(pidSegment.PrimaryLanguage.Identifier.Value.ToLower(), true)
                    }
                }
                ;

                // Marital Status
                fieldNo = 16;
                if (!pidSegment.MaritalStatus.IsEmpty())
                {
                    retVal.MaritalStatus = pidSegment.MaritalStatus.ToModel(MaritalStatusCodeSystem);
                }

                // Religion
                fieldNo = 17;
                if (!pidSegment.Religion.IsEmpty())
                {
                    retVal.ReligiousAffiliation = pidSegment.Religion.ToModel(ReligionCodeSystem);
                }

                // Ethinic groups
                fieldNo = 22;
                if (pidSegment.EthnicGroupRepetitionsUsed > 0)
                {
                    retVal.EthnicGroupCodeKey = pidSegment.GetEthnicGroup().First().ToModel(EthnicGroupCodeSystem).Key;
                }

                fieldNo = 18;
                // Patient account, locate the specified account
                if (!pidSegment.PatientAccountNumber.IsEmpty())
                {
                    var account = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Account> >()?.Query(o => o.Identifiers.Any(i => i.Value == pidSegment.PatientAccountNumber.IDNumber.Value), AuthenticationContext.SystemPrincipal).FirstOrDefault();
                    if (account != null)
                    {
                        retVal.Participations.Add(new ActParticipation(ActParticipationKey.Holder, retVal)
                        {
                            SourceEntityKey = account.Key
                        });
                    }
                    else
                    {
                        retVal.Participations.Add(new ActParticipation(ActParticipationKey.Holder, retVal)
                        {
                            SourceEntity = new Account()
                            {
                                Identifiers = new List <ActIdentifier>()
                                {
                                    new ActIdentifier()
                                    {
                                        Authority = pidSegment.PatientAccountNumber.AssigningAuthority.ToModel(),
                                        Value     = pidSegment.PatientAccountNumber.IDNumber.Value
                                    }
                                },
                                StatusConceptKey = StatusKeys.New
                            }
                        });
                    }
                }

                // SSN
                fieldNo = 19;

                // Patient account, locate the specified account
                if (!String.IsNullOrEmpty(pidSegment.SSNNumberPatient.Value))
                {
                    var ssn = pidSegment.SSNNumberPatient.Value;
                    // Lookup identity domain which is designated as SSN , if they already have one update it, if not, add it
                    var existing = retVal.Identifiers.FirstOrDefault(o => o.Authority.DomainName == this.m_configuration.SsnAuthority?.DomainName);
                    if (existing == null)
                    {
                        retVal.Identifiers.Add(new EntityIdentifier(this.m_configuration.SsnAuthority, ssn));
                    }
                    else
                    {
                        existing.Value = ssn;
                    }
                }

                // Birth place is present
                fieldNo = 23;
                if (!pidSegment.BirthPlace.IsEmpty()) // We need to find the birthplace relationship
                {
                    var existing = retVal.Relationships.FirstOrDefault(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Birthplace);

                    if (Guid.TryParse(pidSegment.BirthPlace.Value, out Guid birthPlaceId))
                    {
                        if (existing == null)
                        {
                            retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Birthplace, birthPlaceId));
                        }
                        else
                        {
                            existing.TargetEntityKey = birthPlaceId;
                        }
                    }
                    else
                    {
                        var places = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Names.Any(n => n.Component.Any(c => c.Value == pidSegment.BirthPlace.Value)), AuthenticationContext.SystemPrincipal).Where(o => this.m_configuration.BirthplaceClassKeys.Contains(o.ClassConceptKey.Value));
                        if (places.Count() == 1)
                        {
                            if (existing == null)
                            {
                                retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Birthplace, places.First().Key));
                            }
                            else
                            {
                                existing.TargetEntityKey = places.First().Key;
                            }
                        }
                        else
                        {
                            throw new KeyNotFoundException($"Cannot find unique birth place registration with name {pidSegment.BirthPlace.Value} ({places.Count()} results found). Try using UUID.");
                        }
                    }
                }

                // MB indicator
                if (!pidSegment.MultipleBirthIndicator.IsEmpty())
                {
                    retVal.MultipleBirthOrder = pidSegment.MultipleBirthIndicator.Value == "Y" ? (int?)-1 : null;
                }
                if (!pidSegment.BirthOrder.IsEmpty())
                {
                    retVal.MultipleBirthOrder = Int32.Parse(pidSegment.BirthOrder.Value);
                }

                // Citizenship
                fieldNo = 26;
                if (pidSegment.CitizenshipRepetitionsUsed > 0)
                {
                    foreach (var cit in pidSegment.GetCitizenship())
                    {
                        var places = ApplicationServiceContext.Current.GetService <IDataPersistenceService <Place> >()?.Query(o => o.Identifiers.Any(i => i.Value == cit.Identifier.Value && i.Authority.Key == AssigningAuthorityKeys.Iso3166CountryCode), AuthenticationContext.SystemPrincipal);
                        if (places.Count() == 1)
                        {
                            retVal.Relationships.Add(new EntityRelationship(EntityRelationshipTypeKeys.Citizen, places.First().Key));
                        }
                        else
                        {
                            throw new KeyNotFoundException($"Cannot find country with code {cit.Identifier.Value}");
                        }
                    }
                }

                // Death info
                fieldNo = 29;
                if (!pidSegment.PatientDeathIndicator.IsEmpty())
                {
                    retVal.DeceasedDate = pidSegment.PatientDeathIndicator.Value == "Y" ? (DateTime?)DateTime.MinValue : null;
                }
                if (!pidSegment.PatientDeathDateAndTime.IsEmpty())
                {
                    retVal.DeceasedDate          = pidSegment.PatientDeathDateAndTime.ToModel();
                    retVal.DeceasedDatePrecision = pidSegment.PatientDeathDateAndTime.ToDatePrecision();
                }

                // Last update time
                if (!pidSegment.LastUpdateDateTime.IsEmpty())
                {
                    retVal.CreationTime = (DateTimeOffset)pidSegment.LastUpdateDateTime.ToModel();
                }

                //if(!pidSegment.LastUpdateFacility.IsEmpty())
                //{
                //    // Find by user ID
                //    var user = ApplicationServiceContext.Current.GetService<IDataPersistenceService<SecurityUser>>().Query(u=>u.UserName == pidSegment.LastUpdateFacility.NamespaceID.Value).FirstOrDefault();
                //    if (user != null)
                //        retVal.CreatedBy = user;
                //}

                if (motherEntity != null)
                {
                    retCollection.Add(motherEntity);
                }
                retCollection.Add(retVal);
                return(retCollection);
            }
            catch (HL7ProcessingException e) // Just re-throw
            {
                throw;
            }
            catch (HL7DatatypeProcessingException e)
            {
                throw new HL7ProcessingException("Error processing PID segment", "PID", pidSegment.SetIDPID.Value, fieldNo, e.Component, e);
            }
            catch (Exception e)
            {
                throw new HL7ProcessingException("Error processing PID segment", "PID", pidSegment.SetIDPID.Value, fieldNo, 1, e);
            }
        }
예제 #29
0
 /// <summary>
 /// Updates an assigning authority.
 /// </summary>
 /// <param name="assigningAuthorityId">The id of the assigning authority to be updated.</param>
 /// <param name="assigningAuthorityInfo">The assigning authority info containing the updated information.</param>
 /// <returns>Returns the updated assigning authority.</returns>
 public AssigningAuthority UpdateAssigningAuthority(Guid assigningAuthorityId, AssigningAuthority assigningAuthorityInfo)
 {
     return(this.Client.Put <AssigningAuthority, AssigningAuthority>($"AssigningAuthority/{assigningAuthorityId}", assigningAuthorityInfo));
 }
예제 #30
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AssigningAuthorityInfo"/> class
 /// with a specific assigning authority.
 /// </summary>
 public AssigningAuthorityInfo(AssigningAuthority assigningAuthority)
 {
     this.Id = assigningAuthority.Key.GetValueOrDefault(Guid.Empty);
     this.AssigningAuthority = assigningAuthority;
 }