go to post Jeffrey Drumm · Dec 17, 2019 If you could provide a little more detail on your use case, there may be a solution that doesn't involve developing a custom service. For example, you could configure the service with a filename pattern that would retrieve all matching files in the target path, but discard, via a routing rule, any that do not meet the date criteria. The name of the file should be available in the Source property of the message object.
go to post Jeffrey Drumm · Dec 16, 2019 printf formatting tokens (%Y, %m, %d, etc.) are not wildcard characters. You'll be limited to legal file naming characters and OS/Shell specific wildcard characters such as * and ? for fetching files.
go to post Jeffrey Drumm · Dec 12, 2019 Select something for the "In files/file types:" field, then enter a search value. You can also do it in reverse order, but both fields are required
go to post Jeffrey Drumm · Dec 5, 2019 You haven't specified an iteration for ORCgrp(). If there's only one ORC group in your messages, you should use ORCgrp(1).
go to post Jeffrey Drumm · Dec 5, 2019 If the layout of each record is identical, a simple record map populated through a BPL/DTL combo would be the preferred solution.
go to post Jeffrey Drumm · Nov 27, 2019 Define them as properties in your task class: Class User.Task.MessageArchive Extends %SYS.Task.Definition { /// Base directory for the archived files Property BaseDir As %String [ InitialExpression = "/hsf/archive/" ]; /// The date of the 24 hour period from which the messages will be selected (midnight to midnight) Property DaysOld As %Integer [ InitialExpression = 23 ]; /// When selected, messages received from services will be archived Property MessagesInbound As %Boolean [ InitialExpression = 1 ]; /// When selected, messages sent to operations will be archived Property MessagesOutbound As %Boolean [ InitialExpression = 1 ]; /// Send Notification Email Property NotifyByEmail As %Boolean [ InitialExpression = 0 ]; These properties can then be referenced in your task's methods with the .. prefix notation.
go to post Jeffrey Drumm · Nov 24, 2019 I've done something similar with COS, but in my case it was the ORC group that was repeating: Class HICG.Process.MultiORC Extends Ens.BusinessProcess [ ClassType = persistent ] { Property TargetConfigNames As %String(MAXLEN = 1000); Parameter SETTINGS = "TargetConfigNames:Basic:selector?multiSelect=1&context={Ens.ContextSearch/ProductionItems?targets=1&productionName=@productionId}"; Method OnRequest(pRequest As EnsLib.HL7.Message, Output pResponse As Ens.Response) As %Status { Set tORCcnt = pRequest.GetValueAt("PIDgrpgrp(1).ORCgrp(*)") For i=1:1:tORCcnt { Set tMsg = ##class(EnsLib.HL7.Message).%New() Set tMsg.DocType = pRequest.DocType // Keep MSH:10 unique Set tMsgCtrl = pRequest.GetValueAt("MSH:10")_"."_i Do tMsg.SetValueAt(pRequest.GetValueAt("MSH"),"MSH") Do tMsg.SetValueAt(tMsgCtrl,"MSH:10") Do tMsg.SetValueAt(pRequest.GetValueAt("PIDgrpgrp(1).PIDgrp.PID"),"PIDgrpgrp(1).PIDgrp.PID") Do tMsg.SetValueAt(pRequest.GetValueAt("PIDgrpgrp(1).PIDgrp.PV1grp.PV1"),"PIDgrpgrp(1).PIDgrp.PV1grp.PV1") Do tMsg.SetValueAt(pRequest.GetValueAt("PIDgrpgrp(1).ORCgrp("_i_").ORC"),"PIDgrpgrp(1).ORCgrp(1).ORC") Do tMsg.SetValueAt(pRequest.GetValueAt("PIDgrpgrp(1).ORCgrp("_i_").OBR"),"PIDgrpgrp(1).ORCgrp(1).OBR") Set tOBXcnt = pRequest.GetValueAt("PIDgrpgrp(1).ORCgrp("_i_").OBXgrp(*)") For j=1:1:tOBXcnt { Do tMsg.SetValueAt(pRequest.GetValueAt("PIDgrpgrp(1).ORCgrp("_i_").OBXgrp("_j_").OBX"),"PIDgrpgrp(1).ORCgrp(1).OBXgrp("_j_").OBX") } Set tSC = tMsg.%Save() $$$TRACE(tSC) For iTarget=1:1:$L(..TargetConfigNames, ",") { Set tTarget=$ZStrip($P(..TargetConfigNames,",",iTarget),"<>W") Continue:""=tTarget Set tSC1 = ..SendRequestAsync(tTarget,tMsg) Set:$$$ISERR(tSC1) tSC=$$$ADDSC(tSC,tSC1) } } Return tSC }
go to post Jeffrey Drumm · Oct 16, 2019 The audit log can provide information on who changed a production configuration, such as adding or modifying a business host configuration. It does not contain information on who modified or created a routing rule, DTL, BPL or other class associated with running a production. For the latter you should consider implementing a Source/Version control system that controls how those components progress from development through QA to Prod and tracks who made those changes. Deltanji from George James Software is a strong contender in that area.
go to post Jeffrey Drumm · Oct 13, 2019 Did you select EnsLib.HL7.Service.SOAPService as your service's class? If yes, then I know the following XML format works: <?xml version="1.0" encoding="UTF-8" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'> <SOAP-ENV:Body> <Send xmlns="http://tempuri.org"> <Input> <![CDATA[MSH|^~\&|... rest of hl7 message here, with <CR><LF> at end ]]> </Input> </Send> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
go to post Jeffrey Drumm · Oct 12, 2019 I'm assuming you don't have "Act on Validation Error" enabled in the router's settings ... in which case the message will be set to Completed status even though it failed validation. If you enable "Act on Validation Error" its status will be set to Error; you'll then be able to select for that status in the Message Viewer and resend. Note that with this setting enabled, you may want to set "Reply Code Actions" to do something other than the default, such as sending the messages to the Suspended Messages facility. Another option would be to specify a Bad Message Handler; this forwards failed validations to a business host where other actions can be taken such as alerting or logging to a file. You'll also have the option of resubmitting those messages to their original destination by specifying a new target in the Message Viewer's Resend facility.
go to post Jeffrey Drumm · Sep 30, 2019 I've found that the MessageStructure component is, more often than not, unvalued. This should do the trick for all cases where there is a minimally compliant MSH:9 field: $REPLACE($PIECE(pRequest.GetValueAt("MSH:MessageType"),pRequest.CS,1,2),pRequest.CS,"")
go to post Jeffrey Drumm · Sep 19, 2019 Hey, Vic. Thanks again ... I'm opening an HL7 message body. Set tMsg=##class(EnsLib.HL7.Message).%OpenId(tId,0) I'm then writing it to a stream object: Set tSC=tMsg.OutputToLibraryStream(tObj) The error appears when outputting to the stream.
go to post Jeffrey Drumm · Sep 18, 2019 Looking at the docs, %OpenId() accepts a concurrency argument. 0 is "no lock," but when using it on a mirror backup I get:ERROR #939: Insufficient privilege for object access 'EnsLib.HL7.Message::%Open'Not sure what privilege I can be granted to allow it as I'm running it with the %All role ... but I get the feeling I'm barking up the wrong tree.
go to post Jeffrey Drumm · Sep 17, 2019 Yes, that's the purpose of the EnsLib.HL7.Operation.FileOperation class.
go to post Jeffrey Drumm · Sep 17, 2019 Thanks Vic for the confirmation and explanation.What I still can't figure out, though, is why a lock is needed to read a message body from the database and write it to flat file. Practically speaking I don't need the lock ... the message has almost reached its sell-by date and will be purged from the database within the week. It's never going to be modified again.A DR Async/Reporting member is a possibility, but not for the near term ...
go to post Jeffrey Drumm · Sep 6, 2019 1. Sure, this will work find for just passing a file through to the target system.2. Yes. You can use public/private key authentication as well.3. Do you really want to put the files into the root directory? Normally, a FTP/SFTP server will default to the "home" directory for the account your operation logs in under. If you don't specify a path, that's where the data you're transferring will end up. If the account has its home directory set to the root directory and has permission to write there, your files will end up there.4. You'll need to set the SSL configuration to the special value "!SFTP". There's no profile for it; it's just an indicator for the operation that you'll be using the SFTP protocol.
go to post Jeffrey Drumm · Sep 4, 2019 As long as you can count on the message spec never changing, this works fine.If the originating system ever adds an NTE segment after the OBX, you'll have an issue. The message would still be valid from an HL7 standards perspective, though.
go to post Jeffrey Drumm · Aug 27, 2019 Hi Scott,The upgrade instructions for HealthShare/HealthConnect 2018.1.2 should be essentially the same as for Caché/Ensemble 2018.1.2. The documentation for the latter is here:https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls
go to post Jeffrey Drumm · Aug 22, 2019 Thanks, Leon. Good to hear that you're still active in healthcare integration, and I hope we'll see more of you here at the Developer's Community!