go to post Ashok Kumar · Sep 10, 2023 Thank you @Robert Cemper for spending time on the evaluation on the IntegrityLog-Web , CSPFileViewDownload and System-Task-REST and provided valuable feedback.
go to post Ashok Kumar · Sep 8, 2023 Hello Scott, You have lot of object properties declared in your class definition. So, You should initialize the parameter to handle the unexpected fields like extending the %JSON.Adaptor in your class definitions. Otherwise it throw an error. So, Make sure the %JSONFIELDNAME was added if the JSON field name is different from your property and add parameter %JSONIGNOREINVALIDFIELD to avoid unexpected field while loading JSON into object. Here is the article about the JSON adaptor Parameter %JSONIGNOREINVALIDFIELD As BOOLEAN = 1 Yes, You can order your JSON structure by rearranging the property back and forth.
go to post Ashok Kumar · Sep 8, 2023 Hi Prashant, You can get the values from %Metadata.columns.GetAt(i).ODBCType the ODBC type is referred the datatype of the column. 12 for VARCHAR refer the ODBC type integer and datatype here ClassMethod GetColumnType() As %String { set statement = ##class(%SQL.Statement).%New() set tSC = statement.%PrepareClassQuery("Sample.Person","TestQuery") set result = statement.%Execute() #dim meta As %SQL.StatementMetadata set meta = result.%GetMetadata() write meta.columns.GetAt(1).ODBCType ;fetch first field }
go to post Ashok Kumar · Sep 8, 2023 Hi @Gautam Rishi , You can use the GetColumnType(columnnumber) to get the datatype of the particular field in the result set object. This GetColumnType Method returns an integer values from 1 to 20.each number represent unique datatype( 10 represents VARCHAR ). If the type cannot be determined, 0 is returned. For Dynamic SQL use %SQL.Statement It's preferable and suggested instead %Resultset. set result = ##class(%ResultSet).%New("Class:Query") while result.Next() { for I=1:1:result.GetColumnCount() { write "Column Name: ",result.GetColumnName(I),! write "Datatype: ",result.GetColumnType(I),! } } Column Name: FirstNameDatatype: 10Column Name: LastNameDatatype: 10
go to post Ashok Kumar · Sep 7, 2023 This is really useful when we working long strings. If we didn't declare any stream object for the temp variable and pass to %ToJSON(temp). In that case, a %Stream.FileCharacter stream is created
go to post Ashok Kumar · Sep 7, 2023 Hello David, Both object script and SQL transaction rollback's are captured in log once you enabled the setting is true System > Configuration > Compatibility Settings > Edit Compatibility Settings for rollback log USER>write $ZVIRIS for Windows (x86-64) 2023.1 (Build 229) Fri Apr 14 2023 17:36:18 EDTUSER>tstart TL1:USER>set ^TEST=1 TL1:USER>trollback log entry
go to post Ashok Kumar · Sep 7, 2023 This is nice. Anyway there are few suggestions Make sure the commands and string functions are following same format either SET or Set or set Use %DynmaicArray instead of literal constructors [ ]. Because it's instantiate the methods of the object like %push when accessing it. Literal constructors won't do it. Comments are essential for better understanding the program flow. Anyway if you don't want to appear your comments in INT code then use the syntax #; instead of ; ex: #;Test comment Use $ListNext to get the list values one by one. It rid out the 2 additional string functions $LISTLENGTH and $LISTGET usage in your case. Easy to understand You can use $Increment instead of declaring a questionNumber variable and do addition operation in the code. Add some conditional checks to skip the if the values in between | is empty I have attached the code sample below. ClassMethod createResponse(data As %String(MAXLEN="")) As %DynamicArray { set items = ##class(%DynamicArray).%New() #;1.- Questions splitted by "|" set ptr=0 set listQuestions = $ListFromString(data, "|") #;2.- Iterate while $ListNext(listQuestions,ptr,questionAnswer) { #;3.- Update variables continue:questionAnswer="" set question= $Piece(questionAnswer, ":", 1) set answer = $ZStrip($PIECE(questionAnswer, ":", 2), "<W") //Get rid of initial whitespace #;4.- Generate item set item = { "definition": ("question "_($Increment(questionNumber))), "text": (question), "answer": [ { "valueString": (answer) } ] } do items.%Push(item) } return items } Hope this helps
go to post Ashok Kumar · Sep 5, 2023 The HS.SDA3.TimeStamp datatype class accepts both YYYY-MM-DDT00:00:00Z and YYYY-MM-DDT00:00:00 values but truncates the additional date values if the length is more than 19 in some system methods such as IsValid, LogicalToXSD methods while performing exports. I have verified and This changes happened whenever it converts to XML. However the actual entire value is persist YYYY-MM-DDT00:00:00Z in the container object. Container object have capability to export both XML and JSON as a stream by using ToJSON() method. You can run the DTL programmatically to get the container object to verify. SAMPLES> write container2@HS.SDA3.ContainerSAMPLES> write container.Patient3@HS.SDA3.PatientSAMPLES> write container.Patient.BirthTime1993-12-12T00:00:00Z I used the DTL generated container object value for another DTL source to generate a FHIR discrete resource. It works. The BirthTime is same as the expected value { "resourceType": "Patient", "birthDate": "1993-12-12T00:00:00Z" }
go to post Ashok Kumar · Sep 5, 2023 Hello @Smythe Smythee There is no difference between ensemble and IRIS instance. In your case, the source.MemberDOB is an date( ex 01/01/2000) and the conversion is working perfectly. Can you check the input of the memberDOB before conversion and just take a quick look of the previous samples. USER>write $ZVIRIS for Windows (x86-64) 2023.1 (Build 229) Fri Apr 14 2023 17:36:18 EDTUSER>set DOB="01/01/1999" USER>write $translate($ZDT($ZDTH(DOB),3)," ","T")_"Z"1999-01-01T00:00:00Z The same code is works in IRIS Interoperability DTL as well. <assign value='$translate($ZDT($ZDTH(source.DOB),3)," ","T")_"Z"' property='target.{PID:DateTimeofBirth}' action='set' />
go to post Ashok Kumar · Sep 2, 2023 AFAIK No. There is no straightforward way to import JSON from FHIR discrete resources to SDA3 objects by %JSONImport(). Basically, there are various stages involved in converting the FHIR to HL7 and vice versa. To achieve this, Intersystems created an intermediary format called SDA. However, there are more processes involved whenever convert the bundle or discrete resource.for example In some instances, the FHIR resource data element name (property) is not the same as the SDA property. Lots of internal DTL's are invoked or invoked at the conversion time, and an SDA object is created based on that output. Typically it's common for SDA to FHIR and vice versa. DTL's are crucial to accomplish this conversion. Some of the data elements are not mapped in the standard FHIR to SDA or SDA to FHIR DTL transformation. HS.FHIR.DTL.vR4.SDA3.AllergyIntolerance.Allergy in this DTL the "criticality" data element is not mapped with SDA object In this case you should create your custom DTL from the already implemented DTL to convert the values to object. So If you haven't added this type of additional properties in the SDA extension class, it won't work. Metadata values and lookup tables vary from SDA to FHIR. SDA has 'A' in the lookup tables for some fields, while FHIR has 'Active'. There is a internal validation runs against every data element to verify the generated FHIR resource Every time
go to post Ashok Kumar · Sep 2, 2023 You're absolutely right.It's crucial, We really need to build it for IRIS.
go to post Ashok Kumar · Aug 31, 2023 You need to call. If it's was declared as method. I tried the below and it works. <script language=cache method="montaDDList" arguments=""> Set listaPropriedades=$SYSTEM.SQL.Execute("SELECT * from Sample.Person") </script> #(..montaDDList())#
go to post Ashok Kumar · Aug 31, 2023 The reason behind the conversion is Cache identifies/assume from 1900 - 1999 year if you send two digit for year. So, You should send four digit year. attached the documentation "Two or four digits may be specified for years in the range 1900 to 1999. Four digits must be specified for years before 1900 or after 1999."
go to post Ashok Kumar · Aug 29, 2023 As per your code. Couple of things. Firstly, the item is list of object so you should use Insert method. You're inserting item.ItemName instead item object. Property Item As list Of AllItems; expects object. Not a string. Do AllItem.Item.Insert(Item)
go to post Ashok Kumar · Aug 29, 2023 %JSON.Adaptor default manner is rid out the null value properties when %JSONExport method invokes. There is some default parameter are used to achieve this while exporting. You need to enable parameter in your class definition. The %JSONNULL parameter is used to export all the field and display even the property has null values. Once you have added the parameter and try export the itemdetails object Parameter %JSONNULL As BOOLEAN = 1; Class Samples.AllItems Extends (%JSON.Adaptor, Ens.Response) { Parameter %JSONNULL As BOOLEAN = 1; Property ItemtId As %String; Property itemName As %String(MAXLEN = 100); Property itemStockNumber As %String(MAXLEN = 150); Property itemType As %String; Property itemPriority As %String; Property itemDetailData As %String(MAXLEN = 10000); } { "ItemId": "test", "Item": [ { "ItemtId": null, "itemName": null, "itemStockNumber": 123, "itemType": "test", "itemPriority": "High", "itemDetailData": null } ]}
go to post Ashok Kumar · Aug 28, 2023 Thank you @Dan Pasco. It's a wonderful detailed clarification for the property and member type class
go to post Ashok Kumar · Aug 24, 2023 Hello @Hannah Sullivan If you need to delete the list of object while deleting the parent object. You can override the %OnDelete method and add the delete implementation refer below code logic. Once you call the ##Class(package.class).%DeleteId(id). It will trigger the %OnDelete Method and delete the list of persistent object as well. ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private, ServerOnly = 1 ] { set object = ..%Open(oid,,.status) If $$$ISERR(status) quit status If $IsObject(object.Organizations) { set org= object.OrganizationsGetSwizzled() while org.GetNext(.key){ do object.Organizations.GetAt(key).%DeleteId(key) } } Quit $$$OK } You can create these object with Parent-child relationship as well.
go to post Ashok Kumar · Aug 24, 2023 I'm not sure why the request class CSVtoHL7.Inputfile.Record inherits from right. All the request and response are required persistent object. This will be used to display the entire flow in the visual trace section. I have attached some sample below. You can add a property setter method for property DOB and modify the value from MM/DD/YYYY to +$H value. This will keep the internal date format in database. Class CSVtoHL7.Inputfile.Record Extends (Ens.Request, %XML.Adaptor, EnsLib.RecordMap.Base) [ ProcedureBlock ] { Property ID As %Integer; Property LastName As %String; Property FirstName As %String; Property MiddleName As %String; Property DOB As %Date; Method DOBSet(pDate) As %Status { Set i%DOB= $ZDH(pDate) Quit $$$OK } Property Gender As %String; ClassMethod createObj() As CSVtoHL7.Inputfile.Record { Set obj = ##class(CSVtoHL7.Inputfile.Record).%New() Set obj.DOB="12/30/2001" Set obj.FirstName="Test" Set obj.ID=12345 Set obj.MiddleName = "middle" Set obj.Gender="M" return obj } } Create a object for the request class and send to Transformation. you can use the logic $translate($ZDT(source.DOB_",0",3)," ","T")_"Z" in DTL to convert the internal date format to required output 2023-08-24T00:00:00Z. You can refer the DTL sample below Class CSVtoHL7.DTL.Record Extends Ens.DataTransformDTL [ DependsOn = (CSVtoHL7.Inputfile.Record, EnsLib.HL7.Message) ] { Parameter IGNOREMISSINGSOURCE = 1; Parameter REPORTERRORS = 1; Parameter TREATEMPTYREPEATINGFIELDASNULL = 0; XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ] { <transform sourceClass='CSVtoHL7.Inputfile.Record' targetClass='EnsLib.HL7.Message' targetDocType='2.5:ADT_A01' create='new' language='objectscript' > <assign value='source.ID' property='target.{PID:SetIDPID}' action='set' /> <assign value='source.FirstName' property='target.{PID:PatientName().FamilyName}' action='set' /> <assign value='source.MiddleName' property='target.{PID:PatientName().GivenName}' action='set' /> <assign value='source.Gender' property='target.{PID:AdministrativeSex}' action='set' /> <assign value='$translate($ZDT(source.DOB_",0",3)," ","T")_"Z"' property='target.{PID:DateTimeofBirth.Time}' action='set' /> </transform> } } output