ir a la publicación Kurro Lopez · 15 mar, 2024 Gracias a la comunidad, tengo un par de respuestas que son válidas. Por si os interesa: Para poder capturar el SessionId Method OnProcessInput( pDocIn As %RegisteredObject, Output pDocOut As %RegisteredObject) As %Status { // here you need to pass the jobid from the %CSP.REST that is invoking the BS set tJobId = pDocIn.JobID // your code here set ^CallApi($CLASSNAME(),tJobId,"sessionid") = ..%SessionId set pDocOut = pDocIn quit $$$OK } El evento que controla cuando ha terminado de procesar la llamada OnEndRequest Ver las réplicas de Guillaume Rongier y de Vitaliy Serdtsev
ir a la publicación Kurro Lopez · 13 feb, 2024 Gracias por tu respuesta. El problema es que no usamos una instancia local, sino que se ejecutan desde otro servidor. Voy a poner en práctica lo que ha recomendado Robert en el foro en inglés. https://community.intersystems.com/post/how-get-job-id-bs-api-rest-debug... Es mas sencillo modificar el valor del global en el servidor y tener el Job para depurar.
ir a la publicación Kurro Lopez · 7 feb, 2024 Según comenta John Murray, esta versión de IRIS tiene un problema con la depuración. https://github.com/intersystems-community/vscode-objectscript/issues/1149 ¿Alguien sabe como hacer una solicitud a WRC para que nos genere un arreglo ad-hoc para IRIS 2021.1.3? He intentado acceder con mi usuario pero no puedo acceder a WRC
ir a la publicación Kurro Lopez · 19 abr, 2023 Voy a poner la respuesta que me han dado en el grupo general y que es una solución muy buena. Muchas gracias @Julian Matthews Hola Kurro. No estoy seguro de una función incorporada para esto, pero si quisieras tener la tuya propia: Class Demo.FunctionSets.Example { ClassMethod Format(InputString As %String, Params... As %String) As %String { Set OutputString = InputString For i = 1 : 1 : $GET(Params, 0){ Set OutputString = $Replace(OutputString,"{"_i_"}",Params(i)) } Quit OutputString } } Y entonces: Write ##Class(Demo.FunctionSets.example).Format("My name is {1} and I'm {2} years","Kurro","18") My name is Kurro and I'm 18 years Podeis ver la respuesta original en el siguiente enlace
ir a la publicación Kurro Lopez · 27 abr, 2022 Al final no era un problema de firewall. El problema era que la instalación no compiló correctamente el código. No tomó la versión de ISC correctamente. Estoy usando la versión WebTerminal-v4.9.3, en la linea 1507 hay una inicialización del parámetro iscProductVersion <Parameter name="iscProductVersion"> <Description> In older Cache versions, method "GetISCProduct" does not exists</Description> <Expression>$case( ##class(%Dictionary.CompiledMethod).IDKEYExists("%SYSTEM.Version", "GetISCProduct"), 1: $CLASSMETHOD("%SYSTEM.Version", "GetISCProduct"), : 2 )</Expression> </Parameter> Después, en la linea 1611, comprueba cuál es la versión para asignar el role requerido: set requiredRole = $case(..#iscProductVersion >= 4, 1: "%DB_IRISSYS", : "%DB_CACHESYS") Pero, si compruebo cuál es mi versión, la respuesta es 3, en lugar de 4, por lo que está intentando asignar %DB_CACHESYS en lugar de %DB_IRISSYS, por lo que la compilación no termina. w ##class(%SYSTEM.Version).GetISCProduct() 3 Entonces, he modificado el fichero y cambiado la comparación ..#iscProductVersion para que compruebe si es mayor o igual a 3, y funciona. En la linea 1730, hay otra comparación para definir el dbPrefix, por lo que he cambiado esta linea también. set dbPrefix = $case(..#iscProductVersion >= 3, 1: "IRIS", : "CACHE") Ahora, tengo Webterminal funcionando bien. Nota: Estoy usando IRIS for Windows (x86-64) 2021.1 (Build 215U) Wed Jun 9 2021 09:39:22 EDT Saludos,Francisco Lopez
ir a la publicación Kurro Lopez · 11 oct, 2021 Investigando un poco mas la documentación de ZEN.Template no resulta complicado implementar nuevos métodos. Siguiendo los mismos pasos que para el asistente SOAP, incluye la siguiente entrada en la lista de links y tendrás nuevos asistentes. Installer Wizard "Installer Wizard": "${serverUrl}/isc/studio/templates/%25Installer.InstallerWizard.cls?Namespace=${namespace}${serverAuth}" DeepSeek PI Wizard "DeepSeek PI Wizard": "${serverUrl}/isc/studio/templates/%25DeepSee.Template.DeepSeeKPIWizard.cls?Namespace=${namespace}${serverAuth}"
ir a la publicación Kurro Lopez · 17 mayo, 2021 (Respuesta de @Eduard Lebedyuk) Ver enlace original en https://community.intersystems.com/post/how-automatically-test-deepsee-p... Aquí algunas ideas Recupera una lista de pivots Por cada elemento Obtén el MDX Intenta ejecutar el MDX Si falla, guarda el error Añade/visualiza los errores Debería de ser factible, DeepSee API tiene todas las funciones necesarias para hacerlo
ir a la publicación Kurro Lopez · 13 mayo, 2021 Hola, Os comento las respuestas obtenidas en el community en inglés. Adjunto también el enlace a la respuesta original. Respuesta de @Robert Cemper https://community.intersystems.com/post/query-method-class-persistent-us... #2) El segundo ejemplo no puede funcionar, principalmente porque no pasa un parámetro en la llamada #1) NO está previsto utilizar propiedades de objeto vomo variables del lengiaje principal en SQL El código falla en el métode Execute generado set tResult = tStatement.%Execute($g(pObject.KeyProcess),$g(pObject.CodeSpecialist),$g(pObject.CodeProvider),$g(pObject.CodeCenter),$g(pObject.Date)) El método $GET object-property simplemente no está implementado. Está definido por la clase y siempre está ahí, pero es necesario y tiene sentido para propiedades multidimensionados Esto es válido para ObjectScript como tal y no está relacionado con SQL.Es como tener un método $g(NOTHING, pObkect.KeyProcess)... osea, nada Alternativas: Manipular directamente el código generado. No recomendado Mover las propiedades con una función auxiliar a variables loclaes y ajusta la consulta con esas variables ClassMethod FillProp(pObject As Kurro.MyClass) As %Boolean [ SqlName = FILLP, SqlProc ] { if '$isObject(pObject) set obj=##class(Kurro.MyClass).%OpenId(pObject) else set obj=pObject set %Kurro("kp")=obj.KeyProcess ,%Kurro("sp")= obj.CodeSpecialist ,%Kurro("pr")= obj.CodeProvider ,%Kurro("cs")= obj.CodeCenter ,%Kurro("dt")= obj.Date quit 1 } Y la invocación sería de esta forma: Query GetInfoRcc(objid As %Integer) As %SQLQuery(CONTAINID = 0, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String") { SELECT IdList, IdProcess, Duration FROM Kurro.MyClass WHERE KeyProcess = :%Kurro("kp") AND CodeSpecialist = :%Kurro("sp") AND CodeProvider = :%Kurro("pr") AND CodeCenter = :%Kurro("cs") AND "Date" = :%Kurro("dt") AND FILLP(:objid) = 1 } Respuesta de @Vitaliy.Serdtsev https://community.intersystems.com/post/query-method-class-persistent-us... Tal y como ha comentado Robert, el problema está en el $GET(), por lo que en lugar de utilizar el método %Library.SqlQuery:Func(), utilizar el PrepareClaseQuery Query GetInfo(pObject AS Kurro.MyClass) As %SQLQuery(CONTAINID = 1, ROWSPEC = "IdList:%String,IdProcess:%String,Duration:%String") [ SqlProc ] { SELECT IdList, IdProcess, Duration FROM Kurro.MyClass WHERE KeyProcess = :pObject.KeyProcess AND CodeSpecialist = :pObject.CodeSpecialist AND CodeProvider = :pObject.CodeProvider AND CodeCenter = :pObject.CodeCenter AND "Date" = :pObject.Date } set obj=##class(Kurro.MyClass).%New() set obj.KeyProcess="1033004-1#" set obj.CodeSpecialist = "surgery" set obj.CodeProvider = "PR002" set obj.CodeCenter = "CENTER-01" set obj.Date = $ZDATETIME($ZDATETIMEH("2021-04-30 15:45:00",3,1),3,1) set st=##class(%SQL.Statement).%New() set sc=st.%PrepareClassQuery("Kurro.MyClass","GetInfo") if $$$ISERR(sc) {write "%PrepareClassQuery failed:" do $System.Status.DisplayError(sc) quit} set result=st.%Execute(obj) do result.%Display() He utilizado la última respuesta para solucionar mi problema y funciona muy bien Mucha gracias a los dos por estas respuestas. Un saludo,Kurro
ir a la publicación Kurro Lopez · 26 ago, 2020 Buenas, en el foro en inglés me han dado varias soluciones y os expongo la que he tomado finalmente He añadido un nuevo método en la clase Request Method Find(item As LabCenter) { for i=1:1:..ListCenter.Count(){ set tmp=..ListCenter.GetAt(i) if tmp.LabId=item.LabId, tmp.Center=item.Center, tmp.Code=item.Code return i } quit 0 } De este modo, encuentro mi Lab-Center > set obj=##class(ListLabCenter).%OpenId(1) > zw obj obj=<OBJECT REFERENCE>[2@ListLabCenter] +----------------- general information --------------- | oref value: 2 | class name: ListLabCenter | %%OID: $lb("1","ListLabCenter") | reference count: 2 +----------------- attribute values ------------------ | %Concurrency = 1 <Set> +----------------- swizzled references --------------- | i%ListCenter = "" | i%ListCenter(1) = $lb($lb("A08829848","A088298480001","")) | i%ListCenter(2) = $lb($lb("A08829848","A088298480002","")) | i%ListCenter(3) = $lb($lb("A08829848","A088298480003","")) | i%ListCenter(4) = $lb($lb("U66700196","U667001960002","")) | i%ListCenter(5) = $lb($lb("U66700196","U667001960003","")) | r%ListCenter = "1@%Collection.ListOfObj" | r%ListCenter(1) = "3@LabCenter" +----------------------------------------------------- > set objFind = ##class(LabCenter).%New() > set objFind.LabId="A08829848" > set objFind.Center="A088298480003" > zw objFind objFind=<OBJECT REFERENCE>[5@LabCenter] +----------------- general information --------------- | oref value: 5 | class name: LabCenter | reference count: 2 +----------------- attribute values ------------------ | Center = "A088298480003" | Code = "" | LabId = "A08829848" +----------------------------------------------------- > w obj.Find(objFind) 3 > set objFindFake = ##class(LabCenter).%New() > set objFindFake.LabId="FAKE" > set objFindFake.Center="A088298480003" > w obj.Find(objFindFake) 0 Un saludo a todos
ir a la publicación Kurro Lopez · 13 jul, 2020 Efectivamente, El problema está en el backspace ($c(8,......)) porque en una simulación en HTML no es reconocido ese caracter. Prueba a cambiar por esta linea: f r v#1 q:(v?.1n) w " !no number", $c(27,91)_12_"D" Esto sería la sentencia ESC[12D que sería lo mismo pero el WebTerminal si sabría interpretarlo Espero que te sirva de mucha ayuda Un saludo, Kurro López
ir a la publicación Kurro Lopez · 10 mar, 2020 Hola Jorge. Bienvenido a la comunidad. En mi empresa tenemos varios proyectos separados por NAMESPACES y cada proyecto tiene un repositorio independiente. Pero a lo mejor te podría servir la forma que lo tenemos distribuido, luego tener el mismo repositorio (GIT, TFS, etc..) para todo el conjunto: 1) Crear un directorio común con todos los namespaces, cada namespace tendrá su propia carpeta 2) Guardar en el directorio principal (Healthshare) el area de trabajo, pero cada carpeta que no sea visible (luego explico el por qué) { "folders": [ { "path": "." }, { "name": "Common", "path": "./COMMON" }, { "name": "Customers", "path": "./CUSTOMERS" }, { "name": "Documents", "path": "./DOCUMENTS" }, { "name": "Hospital", "path": "./HOSPITAL" } ], "settings": { "files.exclude": { "**/.git": true, "Common": true, "Customers": true, "Documents": true, "Hospital": true } }} Quedará el siguiente aspecto en VSCode 3) Configuramos el VSCode ObjectScript de @Dmitry Maslennikov de la siguiente forma: en MyWork.code-workspace. Esta sería la configuración general de conexión con el servidor de Ensemble / ObjectScript "settings": { "files.exclude": { "**/.git": true, "Common": true, "Customers": true, "Documents": true, "Hospital": true }, "objectscript.conn": { "active": true, "host": "localhost", "port": 57772, "username": "_SYSTEM", "password": "SYS", "https": false, "links": {} } 4) En cada uno de los directorios, añadimos una configuración por carpeta con el nombre del namespace que esté trabajando cada subconjunto { "objectscript.conn": { "ns": "COMMON" }} De esta forma cada workspace trabajará con su conexión correspondiente A la hora de subir el repositorio, se sube en Git como cualquier otro fichero, incluso se tendría el equipo totalmente actualizado dado que se podría sincronizar los otros NAMESPACE a la vez y tener actualizado el entorno de desarrollo. Espero que esta forma de distribuición te sirva como nos está sirviendo a nosotros. Un saludo, Francisco López
ir a la publicación Kurro Lopez · 4 mar, 2020 Hola, Para ese tipo de llamadas deberías de usar un adaptador HTTP para conectar con el servidor y leer la respuesta en la propiedad %response Mas info: Using HTTP Adapters with Ensemble Using the HTTP Outbound Adapter Using the HTTP Response No será usar un CURL directamente, pero es una invocación GET/POST/PUT/DELETE a una URL Un saludo, Francisco López
ir a la publicación Kurro Lopez · 20 mayo, 2019 Hola Pilar,Prueba a hacer lo siguiente:1) Crea un recurso para tu WebApi (p.e. ResourceMyApi) Sistema -> Gestión de seguridad -> Recursos2) Generamos un nuevo Rol para asignar este recurso (p.e. RolMyApi) Sistem -> Gestión de seguridad -> RolesAsignamos el recurso a este rol3) Creamos un nuevo usuario para acceder a MyAPi (o abrimos la configuración del usuario que queremos darle los privilegios)Sistema -> Gestión de seguridad -> Usuario -> Editar usuarioAsignamos el rol RolMyApi en la solapa de Roles4) Ahora, en la configuración del WebApi indicamos que es necesario que el usuario tenga el recurso ResourceMyApi para poder acceder.Si intentas acceder con otro usuario verás que recibes un error 401 not authorizedMas información:Caché Security Administration GuideAssets and ResourcesRolesEspero que con esta explicación puedas continuar con tu desarrolloUn saludo,Francisco López