Scott Roth · Oct 3, 2019 go to post

From what I read is the basic purge does not take care of the orphaned messages. That's why there is this manual step we have to configure.

Scott Roth · Oct 15, 2019 go to post

So far we have ended up with like 4 routing rules just for ADT alone to get it do the Ancillary systems.  

Scott Roth · Nov 21, 2019 go to post

I have tried UpgradeAll() also without any luck. Is it possible to just Show and Set qualifiers on just one production to tell me whats wrong with it? I can't open the production class in studio either.

Scott Roth · Nov 21, 2019 go to post

Here is an interesting outcome from playing around. Before I could not open the osuwmc.TestClin in either studio or the Management portal after an upgrade/compile to 2019.1.1.

So I was wondering if I should just look at the file. So I exported it from studio, looked at it on my local desktop, then imported it locally from my desktop. I was able to compile it through studio without issues, and Management Portal was able to see the production as well.

Weird.....

Scott Roth · Jan 6, 2020 go to post

I am struggling with understanding how to display the table within the CSP page. In reading the document it mentions ZEN, but as we have been told not to use ZEN because ZEN is going away.

So how can I display the SQL table in a table format that could be updated instead of the form document mentioned above? Most of the examples are only 1 or 2 rows. I am looking at a 25 rows x 6 columns table to display and update. 

I got the above to work, just trying to make it more friendly.

Thanks

Scott

Scott Roth · Jan 10, 2020 go to post

Everything I have read from Microsoft says this error has to do with a linked server. However where I am trying to select from is a view and has no linked server involved.

Scott Roth · Apr 29, 2016 go to post

I just worked with WRC on this same issue. I was able to make copies of %ZEN.Dialog.finderDialog and EnsPortal.LookupSettings. By using these copies I was able to modify some of the methods to limit down the number of tables a end user would have access too by using a filter on the Naming convention.


Class osuwmc.DataLookup.testFinderDialog Extends %ZEN.Dialog.finderDialog
{
Method GetFinderArray(ByRef pParameters, Output pMetaData, Output pData) As %Status
{
Kill tParms
// assemble search parameters
Set tParms("sort") = ..currSortMode
Set tParms("search") = ..searchKey
Set tParms("abstract") = ..includeAbstract
if (..mode = "labLookup"){
tSC = ##class(%ZEN.FinderUtils).%GetArrayForQuery("Ens.Util.LookupTable","Enumerate",$LB("{Name}","{Name}_"".lut""","lut",""),".",,.pMetaData,.tData)
k=""
for {
k=$order(tData(k))
q:k=""
tableName = $li(tData(k),1)
if (tableName [ "LABS") {
pData($i(pData)) = tData(k)
}
}
tSC
}
else {
Quit ##class(%ZEN.FinderUtils).%GetClassListArray(.tParms,.pMetaData,.pData)
}
}


Class osuwmc.DataLookup.testLookupSettings Extends EnsPortal.LookupSettings
{
/// Handle various dialogs.
ClientMethod onPopupAction(popupName, action, value) [ Language = javascript ]
{
try {
if (action != "ok") {
return false;
}
popupName this.removePopupSuffix(popupName);
switch(popupName) {
case 'NewLookup':
if (value.substring(value.length-4).toUpperCase() != '.LUT') value += '.lut';
// note that we fall through to open the page for both NewLookup and LookupOpen
case 'LookupOpen':
var link zenLink('osuwmc.DataLookup.testLookupSettings.zen');
link += (link.indexOf('?') -1 '&' '?') 'LookupTable=' encodeURIComponent(value);
this.setModified(false);
this.gotoPage(link);
break;
case 'switchNamespace':
zenPage.changeURLNamespace(value);
break;
case 'LookupSaveAs':
if (value.substring(value.length-4).toUpperCase() == '.LUT') value value.substring(0,value.length-4);
zenPage.checkName(value);
break;
}
}
catch (ex) {
alert("Error: " ex);
}
}
/// If the new name is already in use, confirm that the user wishes to overwrite the old table of that name.
ClientMethod checkName(newName) [ Language = javascript ]
{
var duplicateName zenPage.NameCheck(newName);
if (duplicateName !="")
{
if (!confirm($$$FormatText($$$Text("Lookup table name '%1' is already in use! Are you sure you want to overwrite this table?"),duplicateName))) {
return;
}
zenPage.RemoveTable(duplicateName);
}
zenPage.renameSave(newName);
var link zenLink('osuwmc.DataLookup.testLookupSettings.zen');
link += (link.indexOf('?') -1 '&' '?') 'LookupTable=' encodeURIComponent(newName+".lut");
this.setModified(false);
this.gotoPage(link);
}
ClientMethod openTable() [ Language = javascript ]
{
if (this.pageModified) {
var doOpen confirm($$$Text('The current lookup table has been modified. Do you wish to discard these changes and open a different lookup table?'));
if (!doOpen) return;
}
var parms { MODE: "labLookup"};
zenLaunchPopupWindow(zenLink('osuwmc.DataLookup.testFinderDialog.cls'),this.addPopupSuffix('LookupOpen'),'status,scrollbars,resizable=yes,width=800,height=600',parms);
}
Method OnGetRibbonInfo(Output pDisplay As %Boolean, Output pViewIcons As %List, Output pSortOptions As %List, Output pSearchBox As %Boolean, Output pRibbonTitle As %String, Output pCommands As %List) As %Status
{
Set pDisplay = 1
Set pRibbonTitle = $$$Text("Lookup Table Viewer")
Set pCommands(1) = $LB("btnOpen",$$$Text("Open"),$$$Text("Open an existing lookup table"),"zenPage.openTable();")
Set pCommands(2) = $LB("btnSave",$$$Text("Save"),$$$Text("Save the current lookup table"),"zenPage.saveTable();")
Set pCommands(3) = $LB("btnSaveAs",$$$Text("Save As"),$$$Text("Save the current lookup table with a different name"),"zenPage.saveTableAs();")
Quit $$$OK
}
}
 

Scott Roth · Apr 11, 2017 go to post

Here is how I am Calling the Method and Returning me the string

<transform sourceClass='EnsLib.HL7.Message' targetClass='osuwmc.Visit.DataStructures.InsertVisitAttachmentResult' sourceDocType='ORMORUPDF:OSU_ORMORU_PDF' create='new' language='objectscript' >
<assign value='context.TextIDTemp' property='target.TextID' action='set' />
<assign value='source.GetFieldStreamRaw(.tStream,"ORCgrp(1).OBRgrp(1).OBXgrp(1).OBX:ObservationValue(1).AlternateText",.tRemainder)' property='tSC' action='set' />
<assign value='##class(osuwmc.Functions).DecodeBase64HL7ToFile(tStream,source.{MSH:SendingApplication.NamespaceID},source.{PID:PatientIdentifierList(1).IDNumber}_context.TextIDTemp_".pdf")' property='tSC' action='set' />
<assign value='$Get(tSC)' property='target.Text' action='set' />
</transform>

Scott Roth · Jun 20, 2017 go to post

I am looking more for a function that I can call in a Business Rule or Data Transformation to compare the dates.

For example

  • In a Business Rule I might want to say only send messages that have an Admit Date after 7/1/2017.
  • In a Data transformation I might want to say only populate certain fields if Admit Date is after 7/1/2017

Thanks

Scott Roth · Jun 29, 2017 go to post

Have you attempted to use LENGTH?

SayLENGTH(HL7.{MRG. PriorPatientIdentifierList }) > 0

We have never been successful in using the field numbers within our routing rules. Normally we just use the name of the field, or that's at least how we were taught.

I would also think you want to check the message type before you check the MRG.1. So it would be if Message Type is A18 and LENGTH(HL7.{MRG. PriorPatientIdentifierList }) > 0 then return

Scott Roth · Oct 17, 2017 go to post

We found the Ensemble Scheduler single threaded, so If you had schedules that would overlap some instances would not be started correctly. One of my colleagues created two simple command line scripts to start and stop interfaces. We are using those scripts along with the cron scheduler on AIX.

Scott Roth · Oct 19, 2017 go to post

I found my answer, but the question now is how do we set MaxRowsToGet within the Studio Operation for EnsLib.SQL.Snapshot.

Thanks

Scott

Scott Roth · Jan 24, 2018 go to post

When calling a SQL call, I normally return the value in a Snapshot. 

You can do this 1 of two ways...

1. Set two variables....One for the Outbound HL7 Message, and one for the structure of your snapshot. Set your source equal to your snapshot variable and your target being the Outbound HL7 context variable. Use a Data transformation to take the information from the Snapshot and insert it into the HL7.

2. Create a variable for your ID variable, and loop through the Snapshot to set that ID variable. Then create a dummy data transformation that you can use to set your HL7 field to your context.ID variable.

I have plenty of examples of doing this in either way. There might be others that have a better solution, its just what I have used in the past.

Scott Roth

The Ohio State University Wexner Medical Center

Scott Roth · Feb 15, 2018 go to post

Do you have access via Powershell? I was given some AD commands to pull using Powershell. I used this information to make sure the AD Group was being set correctly, and to figure out what to look for in my ZAUTHENTICATE that I am trying to build.

Scott Roth · Feb 19, 2018 go to post

You can use a Data Lookup table to specify the Subject based on the Error you are looking for.

Scott Roth · Mar 12, 2018 go to post

I have used this in the past...

Under my Data Settings I use the following as my Query to act like a status kick off for my job...

SELECT  1

Then my service does...

Method OnProcessInput(pInput As EnsLib.SQL.Snapshot, pOutput As %RegisteredObject) As %Status
{
     set req=##class(osuwmc.CPD.DataStructures.StartJobRequest).%New()
     set req.StartJobStatus = pInput.Get("1")
     set sc = ..SendRequestSync("CPDClarityAddressUpdateBPL",req,.pOutput)
    Quit sc
}

It appears you are not setting your request variable so there is nothing to send to your DQTT.

Scott Roth · Mar 15, 2018 go to post

I have always called it the other way around with the outbound before the I in the Execute Procedure Parm Array.

Method InsertProviderDivisionSp(pRequest As osuwmc.CPD.DataStructures.InsertProviderDivision, Output pResponse As Ens.Response) As %Status
{
set SPQuery = "{ ?= call usp_Interfaces_Insert_ProviderDivision_Ens(?,?,?,?) }"
set par = 4
set par(1) = pRequest.DoctorNumber
set par(2) = pRequest.Division
set par(3) = pRequest.UpdatedBy
set par(4) = pRequest.OrderBy
set tSC = ..Adapter.ExecuteProcedureParmArray(.InsertDivision,.outputs,SPQuery,"oiiii",.par)
if 'tSC write " failed ",tSC 
quit tSC
}
 


or you can call it like...

Method InsertProviderPreference(pRequest As osuwmc.CPD.DataStructures.InsertPreferences, Output pResponse As Ens.Response) As %Status
{
set SPQuery = "{ ?= call usp_Interfaces_Insert_ProviderPreference(?,?,?,?,?) }"
set parm = 6
set parm(1,"SqlType")=$$$SQLVARCHAR
set parm(1,"IOTypes")=$$$SQLPARAMOUTPUT
set parm(2) = pRequest.DoctorNumber
set parm(2,"SqlType")=$$$SQLVARCHAR
set parm(2,"IOTypes")=$$$SQLPARAMINPUT
set parm(3) = pRequest.Preference
set parm(3,"SqlType")=$$$SQLNUMERIC
set parm(3,"IOTypes")=$$$SQLPARAMINPUT
set parm(4) = pRequest.PreferenceValue
set parm(4,"SqlType")=$$$SQLNUMERIC
set parm(4,"IOTypes")=$$$SQLPARAMINPUT
set parm(5) = pRequest.PreferenceDesc
set parm(5,"SqlType")=$$$SQLVARCHAR
set parm(5,"IOTypes")=$$$SQLPARAMINPUT
set parm(6) = pRequest.UpdatedBy
set parm(6,"SqlType")=$$$SQLVARCHAR
set parm(6,"IOTypes")=$$$SQLPARAMINPUT
set tSC = ..Adapter.ExecuteProcedureParmArray(.InsertPreference,.outputs,SPQuery,"oiiiii",.parm)
if 'tSC write "Failed",tSC
quit tSC
}

Scott Roth · May 10, 2018 go to post

What type of database is the stored procedure on? If it is Microsoft have you tried VARCHAR(8000)? MAX does not exist in some SQL languages so sometime you have to limit it down to the number of bytes I believe. Though I might be wrong.

Scott Roth · May 29, 2018 go to post

After many TRACE statements found I was missing (1) after the FT1 in my syntax. So it should be... request.GetValueAt("FT1(1):16.4.2")

Scott Roth · Sep 24, 2018 go to post

In a lot of places I use...

ConvertDateTime (val,in,out,file)

..ConvertDateTime(source.{Z01(1):DateOfBirth},"%Y%m%d","%q(1)")

%q(1) is the format.

We had a consultant write this for us as well...

ClassMethod FormatStringToSQLDate(InDate As %String) As %String [ Final ]
{
If InDate=""
{
set OutDate="1900-01-01 00:00:00"
}
else
{
set DateLength=..Length(InDate)
if (DateLength > 7) && (DateLength < 15)
{
set YYYY=..SubString(InDate,1,4)
set mm=..SubString(InDate,5,6)
set dd=..SubString(InDate,7,8)
set OutDate=YYYY_"-"_mm_"-"_dd
if DateLength=8
{
set OutDate=OutDate_" 00:00:00"
}
if DateLength=10
{
set HH=..SubString(InDate,9,10)
set OutDate=OutDate_" "_HH_":00:00"
}
if DateLength=12
{
set HH=..SubString(InDate,9,10)
set MM=..SubString(InDate,11,12)
set OutDate=OutDate_" "_HH_":"_MM_":00"
}
if DateLength=14
{
set HH=..SubString(InDate,9,10)
set MM=..SubString(InDate,11,12)
set SS=..SubString(InDate,13,14)
set OutDate=OutDate_" "_HH_":"_MM_":"_SS
}
}
else
{
set OutDate="1900-01-01 00:00:00"
}
}
Quit OutDate
}
}
 

Scott Roth · Nov 19, 2018 go to post

Yes I would think the easiest way would be to create a record mapper structure, then use the DTL to map your HL7 fields to where they need to be, then send it to a EnsLib.RecordMap.Operation.FileOperation.

Record Mapper

DTL

Scott Roth · Dec 19, 2018 go to post

With the help from WRC we converted the OBX stream to a GlobalCharacter Stream. See below as an example.

Scott Roth · Jan 3, 2019 go to post

Others can correct me if I am wrong, but everything Intersystems is moving to under the IRIS name.  Think of IRIS as a container with everything running under it.  Health Information Exchange (HIE), Cache Object Script, Globals, Ensemble, and etc run under what they call IRIS.

Zen is Intersystems way of creating Web Pages that talk directly with Cache.

You can use and call globals from any one of the products that you might be using. Globals works across the board, and is just another way of storing the data. In your above example think of the Person global as a variable you can call and retrieve the data

I have a global called OSUWMCLDAP that has various properties I use in some of my class files. I call this global from my class file ie like the following...

Here is examples I use in my class files to retrieve the data from the global.

#define LDAPServer $Get(^OSUMCLDAP("Server"))

Or

$Get(^OSUMCLDAP("Domain"))

Scott Roth · Jan 10, 2019 go to post

Here is a method we built for our use.

ClassMethod IsNumeric(value As %String) As %Boolean
{
//Load value into local var tNumber
set tNumber = value
//Use $extract to get the FULL VALUE into an internal format for $isvalidnum
set tFullValue = $EXTRACT(tNumber,1,$length(tNumber))
//Use $isvalidnum to check if the full value is numeric (ex: 123456789 = true, 123456789x = false)
set tNumberIsValid = $ISVALIDNUM(tFullValue)
//At this point, we simply return tNumberIsValid (it will either be 1, true or 0, false)
quit tNumberIsValid
}
 

Scott Roth · Feb 5, 2019 go to post

You can use split on ZC02, get the length, then for each number that it split you create a separate DFT message.

Scott Roth · Feb 13, 2019 go to post

the Syntax for MAXLEN was wrong. Instead of MAXLEN(5000) it should of been MAXLEN = 5000

Scott Roth · Mar 7, 2019 go to post

With a little help I have built the following Method to Decode and save off the Encoded pdf but return me the directory that I saved the PDF under....

ClassMethod DecodeBase64HL7ToFile(base64 As %Stream.GlobalBinary, Ancillary As %String, FileName As %String) As %String
{
set ArchDir = "/ensemble/data/transfer/AncillaryPDF/"
set ArchAncDir = ArchDir_Ancillary_"/"
set FaxDateDir = ArchAncDir_$PIECE($ZDATE($HOROLOG,7)," ",1)_"-"_$PIECE($ZDATE($HOROLOG,7)," ",2)_"-1/"
if '##class(%Library.File).DirectoryExists(ArchDir)
{
do ##class(%Library.File).CreateDirectory(ArchDir)
 
}
if '##class(%Library.File).DirectoryExists(ArchAncDir)
{
do ##class(%Library.File).CreateDirectory(ArchAncDir)
 
}
if '##class(%Library.File).DirectoryExists(FaxDateDir)
{
do ##class(%Library.File).CreateDirectory(FaxDateDir)
 
}
set Oref = ##class(%FileBinaryStream).%New()
///$$$LOGINFO(FaxDateDir_FileName)
set Oref.Filename = FaxDateDir_FileName
Do base64.Rewind()
While 'base64.AtEnd {
     set ln = base64.ReadLine()
    set lnDecoded = $system.Encryption.Base64Decode(ln)
do Oref.Write(lnDecoded)
}
Do Oref.%Save()
set PDFFilePath = FaxDateDir_FileName
return PDFFilePath
}

Scott Roth · Sep 19, 2019 go to post

Not sure if this will answer your question or not, but we had to move to the jTDS JDBC driver in order to pass an AD account through a connection.

jdbc:jtds:sqlserver://(server name/port) ;instance=tp;domain=osumc;useNTLMv2=true;cacheMetaData=true;prepareSQL=2;