go to post Jeffrey Drumm · Jun 7, 2021 Apologies for digging up this old thread, but this solution doesn't seem to work for IRIS Interoperability Business Operations (and, I'm assuming, Services). Is there A mechanism to get at message header data from within a custom operation?
go to post Jeffrey Drumm · Jun 2, 2021 I think the key to my quest lies here: https://community.intersystems.com/post/how-can-i-get-list-fo-classes-pa...
go to post Jeffrey Drumm · Jun 1, 2021 I guess I answered my own question. Did some poking around and found the data from the dynamic object in global ^EnsLib.H.MessageD, which tells me that the %DynamicObject is persisted as part of the message object. So that's good. I think 😁
go to post Jeffrey Drumm · May 31, 2021 You appear to be attempting to call the method from the debugger. Type Q to return to the normal Cache/IRIS prompt and try again ... let me know what happens. Being in the debugger shouldn't be a problem unless you have the Secure Debug Shell enabled. There are a lot of things you can't do from the debugger when that's enabled, and one of them is using the SET command.
go to post Jeffrey Drumm · May 28, 2021 I tested the method on my own system before posting it, so I'm not sure why you're getting the error. Did you compile the class after saving it? Are you certain the name of the production is spelled correctly? Are you in the proper namespace? EDIT: I also added a tiny bit of error checking to the original method ... note the Return statement after the line Set tPrd...
go to post Jeffrey Drumm · May 28, 2021 Here's a method that might get you close to what you want: ClassMethod GetHostsByAdapter(pProduction As %String, pAdapterName As %String) As %List { Set tPrd = ##class(Ens.Config.Production).%OpenId(pProduction) Return:'$ISOBJECT(tPrd) "Production does not exist!" Set tItems = tPrd.Items Set tItemCnt = tItems.Count() Set tHostList = "" Set tCnt = 1 For i=1:1:tItemCnt { Set tItem = tItems.GetAt(i) If $CLASSMETHOD(tItem.ClassName,"%GetParameter","ADAPTER") = pAdapterName { Set $LIST(tHostList,tCnt) = tItem.Name Set tCnt = tCnt + 1 } } Return tHostList } Call it with: Set hosts=##class(<classname>).GetHostsByAdapter("<production name>","EnsLib.HTTP.InboundAdapter") The variable hosts will contain the list (in $LIST form) of business hosts that have the adapter specified as the 2nd argument.
go to post Jeffrey Drumm · May 4, 2021 I'm posting this as a potential solution. I imagine there are smarter ways of doing this. Hoping someone will jump in and show me the way 😁 I've written a classmethod that accepts 3 arguments: the lower and upper limits of the IDs to select, along with the number of records you'll want to select: Class Sample.Rand { ClassMethod RandList(pMin As %Integer, pMax As %Integer, pLen As %Integer = 10) As %String [ SqlName = List, SqlProc ] { Set tList = "" Set tCnt = 1 For i=1:1:pMax { Set tNum = $R(pMax + 1) If tNum >= pMin { Set $LIST(tList,tCnt) = tNum Set tCnt = tCnt + 1 } Quit:(tCnt > pLen) } Return tList } } The method can be called as a custom SQL function in a subquery: SELECT * FROM MyTable WHERE %Id %INLIST (SELECT Sample.List(MIN(%Id),MAX(%Id),10) FROM MyTable) The query above will select up to 10 rows randomly from table MyTable. Caveats: This could take a long time to run if your range from minimum to maximum %Id is large. And it's not guaranteed to return the number of rows specified as the 3rd argument (there may be deleted records, or insufficient random values generated before the upper limit for %Ids is reached). Finally, it assumes that %Id is numeric. EDIT: And as pointed out by @Julius Kavay, @Robert Cemper has a better idea (he usually does 😉)
go to post Jeffrey Drumm · May 2, 2021 In additional experimentation, I found that there is a quoted-string mechanism: > Set oM."click".type = "double" is equivalent to > Set oM.click.type = "double" Regardless, it's still not persistent.
go to post Jeffrey Drumm · May 1, 2021 No, you can't use the quoted string notation (or at least if you can, I haven't figured out how). It's not persistent either, which is why I followed up to state that it's not really what you're looking for.
go to post Jeffrey Drumm · May 1, 2021 You should need only to iterate over the result set and populate the repetition of the PV1 field. Note that you reference PV1.7 (attending provider) in your narrative, but your code references PV1.3 (assigned patient location), so adjust the below as needed to identify the proper field: //create a copy of the request Set newREQ = pRequest.%ConstructClone() //now we use the copy for manipulation Set res=##class(%ResultSet).%New("%DynamicQueryGW:SQLGW") Set sc=res.Prepare(sqlstring,,conn) Set sc=res.Execute() // create a repetition counter Set cnt=1 While res.Next() { Set RET = res.GetData(2) //Modify the segment //Reference the correct repetition for the current result set member set res = newREQ.SetValueAt(RET,"PV1:3("_cnt_")") //Increment the repetition counter Set cnt=cnt+1 } Set sc=res.Close() Set sc=conn.Disconnect() The appropriate repetition delimiters as defined within the message schema (in this case "~") are automatically inserted. Note that the SetValueAt() method has been modified with the assumption that you're using a consistent HL7 schema across all messages and know the correct path to the PV1 field in question. In that case the FindSegment() method should not be necessary.
go to post Jeffrey Drumm · Apr 30, 2021 Hmm. Upon re-reading your question, I realized this isn't really the answer you were looking for. Others have provided the correct solutions/references.
go to post Jeffrey Drumm · Apr 30, 2021 ClassMethod TestObj() As %DynamicObject { Set oM = {} Set mMode = ["down","up","click"] Set iter = mMode.%GetIterator() While iter.%GetNext(,.val) { Do oM.%Set(val,{"id":"","type":""}) } Quit oM } USER> set oM = ##class(User.DynObj).TestObj() USER> write oM.%ToJSON() {"down":{"id":"","type":""},"up":{"id":"","type":""},"click":{"id":"","type":""}} USER> zwrite oM.down.id "" USER> zwrite oM.up.type "" USER> set oM.click.type = "double" USER> write oM.click.type double USER> write oM.%ToJSON() {"down":{"id":"","type":""},"up":{"id":"","type":""},"click":{"id":"","type":"double"}}
go to post Jeffrey Drumm · Apr 28, 2021 To clarify, are you looking for a method to be used in a Business Process to obtain the path and name of a file created by a Business Operation?
go to post Jeffrey Drumm · Apr 26, 2021 There's a description of this in the documentation. You can find it here: Business Host Versions.
go to post Jeffrey Drumm · Apr 24, 2021 For me, this was a fundamental revelation when I started working with Caché/ObjectScript. Where the $#&! is the sort function/method? I had naively assumed that arrays were simply associative with no intrinsic ordering, like Perl hashes. When the light dawned ... 🤦♀️
go to post Jeffrey Drumm · Apr 1, 2021 Do you have ^EnsPortal("DisableInactivityTimeout","Portal")=1 in each namespace that's running a production? It's not mapped from another namespace.
go to post Jeffrey Drumm · Apr 1, 2021 I'm pretty sure you want the value to be 0 for the second option: set ^%SYS("Portal","EnableAutoRefresh")=0
go to post Jeffrey Drumm · Apr 1, 2021 Have you tried %K(Server) as the output format prefix? HICG>set tm="20210401072630+0000" HICG>w ##class(Ens.Util.FunctionSet).ConvertDateTime(tm,"%q%z","%K(Server)%q%z") 20210401032630-0400 This of course assumes your server is in your locale/time zone.
go to post Jeffrey Drumm · Mar 30, 2021 This might get you closer to what you want, perhaps called from OnProcessMessage() in the service: ClassMethod QueueGetOldest(pQueueName As %String, Output pStatus As %Status) As %String { If ##class(Ens.Queue).GetCount(pQueueName) > 0 { Set tStmt = ##class(%SQL.Statement).%New() set qSC = tStmt.%PrepareClassQuery("Ens.Queue","EnumerateItem") Set tRS = tStmt.%Execute(pQueueName,"") Do tRS.%Next() Set tHdrid = tRS.%Get("MessageId") Set tMsghdr = ##class(Ens.MessageHeader).%OpenId(tHdrid) Set pStatus = $$$OK Return tMsghdr.TimeCreated } Set pStatus = $$$ERROR($$$GeneralError,"Not found") Return "" } It returns the time created of the oldest entry in the queue, or the empty string if the queue is empty or doesn't exist. You could create a variant that would accept a duration argument and return true/false if the duration between the current time and the time of the oldest entry exceeds that.