Julian Matthews · Aug 11, 2022 go to post

Your Process is most likely using ..SendRequestAsync() to send to the Operation and has "pResponseRequired" set to 1 (or not set at all, so it's using the default value of 1).

There's nothing inherently wrong with this, but if you just want to send to the Operation and not worry about the response going back to your process, you could change the "pResponseRequired" flag to 0 in your call. So it would look a little like this:

Set tSC = ..SendRequestAsync("TargetOperationName",ObjToSend,0)

However you may wish to consider if this approach is appropriate to your setup, or if you would be better off using "SendRequestSync()" and dealing with the response synchronously. 

Julian Matthews · Aug 10, 2022 go to post

To parse the json, the below is a starting point for taking the content of the stream into a dynamic object, and then saving the value into its own variable.

Set DynamicObject=[].%FromJSON(pRequest.Stream)
Set Name = DynamicObject.name
Set DOB = DynamicObject.DOB
Set SSN = DynamicObject.SSN

You could then store these wherever you need to. If your SQL table is external, then you could have your Operation using the SQL Outbound Adapter to then write these in your external DB.
ETA: If you then need to pick out the values within the content of name (which I assume has come from a HL7 message) you could use $PIECE to pick out the data from the delimited string you're receiving.

Julian Matthews · Jul 29, 2022 go to post

Hey Daniel.

As a starting point, I would not be adding the trace when viewing the DTL in Studio, and instead I would add it when using the Data Transformation Builder:

Which gives me:

If this is not working for you, make sure that the router has "Log Trace Events" enabled in the router settings and the router has been restarted since enabling the trace. I have been caught out numerous times enabling the trace and then forgetting to restart the process/router in the production.

Julian Matthews · Jul 21, 2022 go to post

The issue of no results being returned is likely elsewhere in your query.

To test this, I created a basic table with the following:

CREATE TABLE Demo.BBQ (
    Name varchar(100),
    Type varchar(50),
    isActive bit
)

And I then added a few rows:

Insert into Demo.BBQ (Name, Type, isActive)
VALUES('Super Grill''s BBQ Hut','Outdoor',1)
Insert into Demo.BBQ (Name, Type, isActive)
VALUES('Bobs BBQ Bistro','Indoor',1)
Insert into Demo.BBQ (Name, Type, isActive)
VALUES('Rubbish Grill''s BBQ Resort','Not Known',0)

This then gave me a table that looks like this (note that the double single quotes used in the insert are inserted as a single quotes into the table):

If I then run a query using the like function:

And if I want to exclude the inactive location:

The use of doubling up a single quote to escape the character is not a Intersystems specific approach, but is generally a standard SQL way of escaping the single quote.

Julian Matthews · Jul 20, 2022 go to post

Lose one of the single quotes where my arrow is (there was a typo in my first reply).

That way your final line should be:

like '%Forceps McGill''s Neonatal NETS%' and i.Active = 1

Julian Matthews · Jul 20, 2022 go to post

There's two ways around this:

  1. If this is something you're running one off in, say, the sql query tool within the management portal, then you will want to repeat the single quote to be "Select * from cnd.Facilities  where name like ''%Grill''s BBQ%'" and this will escape the single quote.
  2. If this is a query being called within your code and the value could be anything passed to it, then you will want to look to use parameterised SQL queries. An example can be found for SQL adapters here.
Julian Matthews · Jul 20, 2022 go to post

Hey Scott.

I'm not sure if this will work at all, but have you tried extending your timeout for your CSP gateway?

Management Portal -> System Administration -> Configuration -> Web Gateway Management is the route to this. The username you'll then need is "CSPSystem" and the password should be the default password used when installing the system.

From within here you can navigate to "Default Parameters" and increase the Server Response Timeout parameter.

Julian Matthews · Jun 20, 2022 go to post

That just means you're one step closer to solving the issue!

What are the data types for each field you're attempting to insert into?

Have you tried just inserting a row with just 1 of the fields populated? Something like:

INSERT INTO Phu_Replay_Schema.ReplayMessageModel (Completed) VALUES (1)
Julian Matthews · Jun 20, 2022 go to post

Hey Lewis.

Could you try swapping out "true" for it's bool equivalent? So try:

INSERT INTO Phu_Replay_Schema.ReplayMessageModel (Completed, MessageHeaderId, NewHeaderId, NewTargetName) VALUES (1, 3616, null, 'Router_ReplayHL7')
Julian Matthews · Jun 14, 2022 go to post

I have to admit, I'm not familiar with where that code has come from, so it's difficult to comment on the syntax.

That said, I think I can confidently say that your first line has the OBXgrp hard coded to the first repetition, but the second line has it set to k2. You will want a for each for the OBXgrp and a seperate one for the NTEs within the OBXgrp.

Julian Matthews · Jun 13, 2022 go to post

Hey Ciaran.

To overcome the issue of multiple ORCs overwriting your PIDgrp NTE in your copy, you will likely need to maintain a separate count of what is being copied over.

So you could look to do something similar to: (pay specific attention to actions 2, 9, and 10) 

Which would then give the following result:

You could then take it a step further by setting the value of your PIDgrp NTE to your count value before incrementing it:

Which would then give you:

As a warning, I did find that the DTL building went a bit weird when it comes to the auto-applying of the key counts. So I was adding a For Each on a repeating field and it assigned a key of say k1, then when adding the sets within the for each loop, it would randomly use k2 or k3 in the field. it might just be a limitation of how I was building things up, but it's one to keep an eye out for as it'll give you unexpected results if it happens to you. Good luck :)

Julian Matthews · Jun 13, 2022 go to post

Hey Eduard, thanks for your detailed reply.

As there is no source message to send in to my specific use case, then a registered class seems to be the way to go!

Julian Matthews · May 19, 2022 go to post

Hey Ephraim.

I have thrown together a task which should do what you need. The code is a bit verbose and could be cut down a touch, but hopefully it's human readable enough for you to pick out what its doing.

Effectively, it takes the current date to then grab a date from last month, and then gets the first and last date of that month to then use in the audit method.

Class Demo.Tasks.MonthlyAudit Extends %SYS.Task.Definition
{

Method OnTask() As %Status
{
    Set tSC = $$$OK

    //Get Current Date
    Set CurentDatetime = $ZDATETIME($HOROLOG,3)

    //The report needs to be for last month, so get a date from last month based on todays date
    Set LastMonth = $SYSTEM.SQL.DATEADD("MM",-1,CurentDatetime)

    //Get last Day of last month As Horolog
    Set LastDayHoro =  $SYSTEM.SQL.LASTDAY(LastMonth)

    //Convert Horolog into a Date
    Set LastMonthEnd = $ZDATETIME(LastDayHoro,3)

    //Get First Day of Last Month
    Set LastMonthStart = $SYSTEM.SQL.DATEPART("YYYY",LastMonthEnd)_"-"_$SYSTEM.SQL.DATEPART("MM",LastMonthEnd)_"-01"

    //Switch to the %SYS Namespace
    ZNspace "%SYS"

    Set tSC = ##class(%SYS.Audit).Export("AuditExport.xml",,,LastMonthStart_" 00:00:00",LastMonthEnd_" 23:59:59")

    Quit tSC
}

}

Then, when setting the task up, I would set it to run on the first Monday of the Month, and it will grab everything from the previous month.

Julian Matthews · Apr 11, 2022 go to post

Hey Ephraim.

You will see from looking at the classmethod being called that there is a start date parameter which was left blank by Michael so that it will export everything up to the end date.

In your case, you could do the following to fulfil your example:

##class(%SYS.Audit).Export("AuditExport.xml",,,"2022-03-01 00:00:00","2022-04-11 23:59:59")

However this will only be useful to your specific date range, which is where Michaels use of $ZDT and $H come into play.

If you wanted to execute the task and have it return the last 30 days, you could do this:

##class(%SYS.Audit).Export("AuditExport.xml",,,$zdt($h-30,3)_" 00:00:00",$zdt($h,3)_" 23:59:59")
Julian Matthews · Apr 4, 2022 go to post

Hey Shamus. I do appreciate you replying, however I may not be being clear in my original question.

Even if I have the correct settings in the Business Service, if the content format is one that conflicts with UTF-8, the display within the management portal will show as per my examples because the browser is trying to display non UTF-8 content as UTF-8. My original question was asking how others work with this.

If you spot my second top-level comment, you will see that I had looked into using the browser to change the http content-type header, but that the major browsers no longer support such a feature.

I'm guessing my only option is to export a message and then review the content there.

Julian Matthews · Apr 4, 2022 go to post

Hey Shamus.

I'm back to eat some humble pie!

Turns out, I had confused myself early on and wrongly believed that Windows-1252/Latin1 were the same and I had my service set to Latin 1. This was then creating a scenario where I was digging myself into a hole of bad information.

In fact, they are almost the same except for the exact characters I was using in my example. These code points are used by Latin-1 as control codes, and when Windows-1252 is mislabeled as Latin-1 they get lost...

Thanks again for replying to my initial question and comments.

Julian Matthews · Apr 1, 2022 go to post

I have looked at how I can change the behavior of the browser, but it seems that the big 3 (well, two) no longer have this feature. Here is an article giving some back story.

Basically, Chrome used to have the option to manually overwrite the encoding type, but this was removed (however there are some 3rd party extensions out there to replace this feature, but I feel uncomfortable using random 3rd party extensions around healthcare data)

Firefox also used to have this feature, but they replaced it with a tool that attempts to repair the character encoding, however it didn't do a great job as it decided it was "IBM866" so the content looked like this:

Julian Matthews · Apr 1, 2022 go to post

Hey Shamus.

My issue isn't with the actual character encoding, but the display of the characters because the management portal (being browser based) uses UTF-8.

In my initial example, if I were to write the output to a file with the the correct character encoding set, it will look fine when opened in a text editor.

Julian Matthews · Mar 24, 2022 go to post

Hey Token.

You could use ##class(%PopulateUtils).VarString() to generate the random string.

Julian Matthews · Mar 7, 2022 go to post

Hey Leon.

The element of this issue that is perplexing me is that there is a difference between the RAW and Full view.

Could you try sending a sample message to a HL7 File operation with the charset set to UTF-8? I'm curious to know if the characters display as expected, stay as the ANSI character, or become something else.

I am wondering if the ANSI displaying in just the Full message viewer is contained to just the display of the full message, and any issues you are seeing in a destination system are a separate but similar issue with character encoding.

Julian Matthews · Mar 3, 2022 go to post

I believe the privilege comes from the OS user that is launching Terminal.

Have you tried running Terminal as an Admin and seeing if runs as expected?

Julian Matthews · Feb 17, 2022 go to post

Hey Kurro.

You should be able to include the allowed source in the rule constraint:

Alternatively, you could add a rule above that looks like this:

Julian Matthews · Feb 1, 2022 go to post

Hey Stefan.

Is the file saved as a class when trying to run the formatter? I found previously that it's not enough to just set the language in a new class, but the file needs to be saved as the formatter relies on the file extension.

Julian Matthews · Dec 29, 2021 go to post

Hey Yuri.

Depending on the context, this answer I gave for a similar question may be relevant:

...you can pass ..Adapter.ExecuteQuery() a snapshot object (EnsLib.SQL.Snapshot) which will then get populated rather than a getting a result set returned. With this populated snapshot object, you can then iterate through it using its Next() method just like the result set, but then you can use its Rewind() method. 

For example:

Set Snapshot = ##Class(EnsLib.SQL.Snapshot).%New()
Set sql = "SELECT * FROM MY_TABLE WHERE X= '"_Y_"'"
Set status = ..Adapter.ExecuteQuery(Snapshot, sql)
While Snapshot.Next(){
  //First run through of snapshot
}
Do Snapshot.Rewind()
While Snapshot.Next(){
  //Second run through of snapshot
}
Julian Matthews · Nov 5, 2021 go to post

Hey Nicola.

As an alternative to Davids response, you can pass ..Adapter.ExecuteQuery() a snapshot object (EnsLib.SQL.Snapshot) which will then get populated rather than a getting a result set returned. With this populated snapshot object, you can then iterate through it using its Next() method just like the result set, but then you can use its Rewind() method. 

For example:

Set Snapshot = ##Class(EnsLib.SQL.Snapshot).%New()
Set sql = "SELECT * FROM MY_TABLE WHERE X= '"_Y_"'"
Set status = ..Adapter.ExecuteQuery(Snapshot, sql)
While Snapshot.Next(){
  //First run through of snapshot
}
Do Snapshot.Rewind()
While Snapshot.Next(){
  //Second run through of snapshot
}

Something to be mindful of - as I'm passing ..Adapter.ExecuteQuery() an object rather than trying to get it to output something, the period before the variable is intentionally missing in my example.

Julian Matthews · Nov 4, 2021 go to post

Thanks John, that's very good to know about.

It's missing 1 or 2 features I like in ScreenToGif, but it's certainly going in my bookmark bar.