Marc Mundt · Nov 8, 2017 go to post

Brendan's post is a related issue, but it's important to note that what he describes only applies if you want to update the value of a specific field when that field contains > 32K of data.  The total size of the message isn't an issue.

As an example: if you have an ORU message with a 10 MB PDF stored in OBX:5, you will still be able to update fields in the PID segment using standard DTL functions. But if you want to update OBX:5 you will need to use the functions that Brendan mentioned.

Marc Mundt · Nov 8, 2017 go to post

The content of an EnsLib.HL7.Message is actually stored in streams, which don't have a fixed size, so theoretically there is no maximum size for an HL7 message.

The RawContent property is a bit misleading. This is a convenience for accessing the content of the message, but it's not where the content is actually stored. RawContent is generated dynamically from the underlying streams but only returns the first 10000 characters.

If you want to access the full, raw, untruncated message you can use one of the OutputTo* methods such as OutputToLibraryStream.

Marc Mundt · Nov 7, 2017 go to post

Hi Stephen,

This can be done with a custom query. See below for some sample code that takes the form of a stored procedure. This stored procedure only handles items in a single namespace, but you could adapt it to run across multiple namespaces.

To call the stored procedure from a SQL query tool:
call Sample.Util_SettingsByName('Port')

The parameter you pass is the name (or names, comma-separated) of the setting(s) you want to get a list of. Leave it blank to get a list of all settings.


Best,
Marc

Class Sample.Util Extends %RegisteredObject
{

/*
         *****************************************************
         *                 ** N O T I C E **                 *
         *               - TEST/DEMO SOFTWARE -              *
         * This and related items are not supported by       *
         * InterSystems as part of any released product.     *
         * It is supplied by InterSystems as a demo/test     *
         * tool for a specific product and version.          *
         * The user or customer is fully responsible for     *
         * the maintenance of this software after delivery,  *
         * and InterSystems shall bear no responsibility nor *
         * liabilities for errors or misuse of this item.    *
         *                                                   *
         *****************************************************
*/
Query SettingsByName(SettingName As %String) As %Query(ROWSPEC = "BusinessHost:%String,SettingName:%String,SettingValue:%String") [ SqlProc ]
{
}

ClassMethod SettingsByNameExecute(ByRef qHandle As %Binary, SettingNames As %String = "") As %Status
{
    s qHandle=##class(%ArrayOfObjects).%New()

    &sql(select %DLIST(id) into :tHostIDs from ENS_Config.Item order by Name desc)
    s tHostIDList=##class(%Library.ListOfDataTypes).%New()
    s tSC=tHostIDList.InsertList(tHostIDs)
    s tSC=qHandle.SetAt(tHostIDList,"HostIDs")

    s tSC=qHandle.SetAt(##class(%ArrayOfDataTypes).%New(),"Counters")
    s tSC=qHandle.GetAt("Counters").SetAt(0,"CurrHost")
    s tSC=qHandle.GetAt("Counters").SetAt(0,"CurrSetting")
    
    if ($L(SettingNames)>1) {
        s SettingNames=$ZCONVERT(SettingNames,"U")
        s tFilterList=##class(%Library.ListOfDataTypes).%New()
        s tSC=tFilterList.InsertList($LISTFROMSTRING(SettingNames))
         s tSC=qHandle.SetAt(tFilterList,"FilterList")
    }

    Quit $$$OK
}

ClassMethod SettingsByNameClose(ByRef qHandle As %Binary) As %Status [ PlaceAfter = SettingsByNameExecute ]
{
    Quit $$$OK
}

ClassMethod SettingsByNameFetch(ByRef qHandle As %Binary, ByRef Row As %List, ByRef AtEnd As %Integer = 0) As %Status [ PlaceAfter = SettingsByNameExecute ]
{
    s tCurrHost=qHandle.GetAt("Counters").GetAt("CurrHost")
    s tCurrSetting=qHandle.GetAt("Counters").GetAt("CurrSetting")
    s tHostIDs=qHandle.GetAt("HostIDs")
    s tFilterList=qHandle.GetAt("FilterList")
    s oHost=qHandle.GetAt("Host")

    do {
        if ('$IsObject(oHost)||(oHost.VirtualSettings.Count()<tCurrSetting)) {
            if (tCurrHost=tHostIDs.Count()) {
                s AtEnd=1
                q
            }

            s tCurrHost=tCurrHost+1
            s tCurrSetting=1
            
            s tHostID=tHostIDs.GetAt(tCurrHost)
            s oHost=##class(Ens.Config.Item).%OpenId(tHostID,0)
            
            s tSC=oHost.PopulateVirtualSettings()

            s tSC=qHandle.SetAt(oHost,"Host")                
            s tSC=qHandle.GetAt("Counters").SetAt(tCurrHost,"CurrHost")
        }

        s tSettings=oHost.VirtualSettings
        s tSetting=tSettings.GetAt(tCurrSetting)
        s tStngName=$LISTGET(tSetting,2)
        s tStngValue=$LISTGET(tSetting,3)
        
        s tCurrSetting=tCurrSetting+1
    } while ($IsObject(tFilterList)&&('tFilterList.Find($ZCONVERT(tStngName,"U"))))
        
    if ('AtEnd) {
        s Row=$LB(oHost.Name,tStngName,tStngValue)
    }
    
    s tSC=qHandle.GetAt("Counters").SetAt(tCurrSetting,"CurrSetting")
        
    Quit $$$OK
}

}

Marc Mundt · Sep 11, 2017 go to post

Salim,

Steps to customize the patient search page are available in the HealthShare documentation. You can navigate to it or search for "Customizing the Patient Search Page".

You should not modify HS.UI.PatientSearch.cls directly -- you should subclass it and override the relevant methods.

Best,
Marc

Marc Mundt · Jun 6, 2017 go to post

There is no standard Ensemble function that accepts multiple values and looks up each one in a lookup table in a single call.

You can achieve this by creating a custom function which accepts a delimited string with all of the values and then iterates through each value and calls the standard "lookup" function once for each value.

Marc Mundt · Jun 6, 2017 go to post

Yes, you just need to wrap them in parentheses and use "||" for "or":

if ((ReceivingFacility="A") || (ReceivingFacility="B") || (ReceivingFacility="C")) {

Or look at using other functions like $LISTFIND or the "[" (contains) operator:

if ($LISTFIND($LISTBUILD("A","B","C"), ReceivingFacility) {

Marc Mundt · Jun 6, 2017 go to post

HTML can be output using normal <item> tags with the copyHtml attribute.

By the way, I see you're a member of QP's team. I'd suggest talking with some of the local Trak technical specialists -- they are experts in Zen reports.

Marc Mundt · Jun 6, 2017 go to post

If you just need to get an output value based on different input values, a lookup table would be the best option.

If you actually need to execute completely different logic depending on the input value, then you can consider using code actions to add a series of ElseIfs, which are much easier to read than deeply nested if blocks.

Marc Mundt · Apr 4, 2017 go to post

Check if the message schema category set on your Business Service matches the schema you chose for the DTL.

Marc Mundt · Dec 8, 2016 go to post

Hi BN,

Can you share some more information about this? 

- What error do you get in SoapUI?
- What does the WSDL generated by your SOAP service look like?

Best,
Marc

Marc Mundt · Nov 28, 2016 go to post

You can use the Ensemble Record Mapper to define a format for fixed format text files. Ensemble can then use the record map you created to ingest the file as a message object which can be transformed to HL7 using standard DTLs.

Marc Mundt · Jul 26, 2016 go to post

You can see this schema/table in management portal if you tick the "System" checkbox to display Caché system tables. Queries against this table will work even if the table doesn't appear in the list.

Marc Mundt · Jul 26, 2016 go to post

You can see this table in the management portal if you tick the "System" checkbox to display Caché system tables.

Marc Mundt · Jul 26, 2016 go to post

You can query the table you found like this:
select * from INFORMATION_SCHEMA.TABLES

I note from the docs you linked that this will only show tables that the current user has privileges for.

Marc Mundt · Jul 19, 2016 go to post

If you plan on doing frequent searches against a specific HL7 segment/field, you can speed up the searches significantly by using Ensemble's "search tables" mechanism for adding an index for that field.
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
Fields indexed in the search table are listed in the dropdown box on the message viewer search, or can be queried using SQL by joining EnsLib_HL7.SearchTable:

select msg.ID,msg.TimeCreated,
       msg.DocType,
       msgHdr.SourceConfigName,
       msgHdr.TargetConfigName,
       msg.RawContent 
from EnsLib_HL7.SearchTable srchTbl
join enslib_hl7.message msg on msg.id=srchTbl.docid 
join Ens.MessageHeader msgHdr on msgHdr.MessageBodyId=srchTbl.docid
where  (srchTbl.propid=(select propid from Ens_Config.SearchTableProp where classextent='EnsLib.HL7.SearchTable' and name='PatientSSN')
       and srchTbl.propvalue = '123-25-4612')
       and msgHdr.SourceConfigName='HL7.File.In'
Marc Mundt · Jul 15, 2016 go to post

It looks like this doesn't work for incoming files. I specified "%Y.txt" as the file spec for EnsLib.HL7.Service.FileService and it fails to pickup a file named "2016.txt".

It's too bad -- these time stamp strings would be perfect, but they seem to only be used when outputting files:

  • Specifying filename for files created by business operations
  • Timestamps appended when a business service archives a file

EnsLib.HL7.Service.FileService

Marc Mundt · Jul 15, 2016 go to post

Maybe someone can offer a more clever solution, but you could create a custom function that you call from the condition field in your routing rule. You would pass it the error information and it would return a boolean for whether or not to send the alert.
Internally the function would use a custom table (or global) which stores the error information and the date/time that error was last alerted. When called it would check the last seen time against a threshold and either return a false to suppress the alert or send a true and then insert/update the error in the table.

Marc Mundt · Jul 13, 2016 go to post

This is more of a Squirrel question so I can't offer specific steps, but on Windows, Java desktop apps are generally started by a .bat file or shortcut which include logic to find the location of the JRE. Usually this just checks if the environment variable JAVA_HOME is set, which I believe is also what Caché does. You could try hardcoding the Squirrel .bat file/shortcut to point to a different JRE.

Marc Mundt · May 11, 2016 go to post

I retract my question.

It seems that the installer encountered a permissions problems during the upgrade so a number of things got broken, including Atelier support.

After re-upgrading, /api/atelier was created correctly and Atelier can connect to the instance.