A veces cuando necesitamos hacer tareas de upgrade o mantenimiento en SAP es necesario que solo determinados usuarios se pueda logear al sistema. Para esto una de las formas en que podemos deshabilitar los ingresos al sistema es de la siguiente forma.
Ingresamos a la transacción SECPOL.
Creamos una nueva Security Policy:
Hacemos click en “New Entries”
Ingresamos un texto y la descripción y hacemos click en guardar.
Seleccionamos la entrada que creamos y hacemos doble click en “Attributes”.
Creamos una nueva entrada.
Ingresamos los siguientes valores:
SERVER_LOGON_PRIVILEGE en name y el valor 1 en Attribute Value.
Damos click a guardar.
Próximo paso es asignarle esta Policy a los usuarios que queremos que PUEDAN logearse al sistema.
Para esto vamos a la transacción SU01 e ingresamos al usuario en modo modificación.
En el tab “Logon Data” en el campo Security Policy le asignamos la Policy que creamos y guardamos.
Por último, debemos ir a la transacción RZ11 y buscar el parámetro:
login/server_logon_restriction
A este parámetro debemos asignarle el valor 1 para que no se pueden logear los usuarios que no tengan esta Policy.
Nos aparecerá la siguiente pantalla:
Hacemos click en “Change Value”
Ingresamos 1 en “New value” y guardamos.
En este momento si algún usuario intenta ingresar le aparecerá el siguiente mensaje.
Para volver a habilitar el ingreso, simplemente volvemos a la RZ11 y seteamos el valor del parametro a 0.
En las ultimas instalaciones del SAP GUI un componente para ver la representación grafica del formulario (SAP SCRIPT) fue removida por SAP, lo que causa un error al hacer click en el boton Layout en la transacción SE71.
El error es:
Graphical Form Painter could not be called (FORMPAINTER_CREATE_WINDOW, )
Para solucionar este error hay que bajar un archivo desde la pagina de soporte de SAP ( https://launchpad.support.sap.com/#/softwarecenter ), desde ahí buscamos SAPSLTESP00_0-70001053.EXE y nos mostrara algo como
Una vez bajado simplemente lo instalamos (Hay que cerrar completamente el SAP GUI) y ya podremos ver la representación grafica del formulario (SAP SCRIPT).
Después de mucho tiempo investigando problemas en unas de mis paginas que surgieron luego de actualizar los certificados SSL, encontré que el problema estaba porque era necesario usar un certificado wildcard, esto es necesario si queremos que no aparezcan errores de certificados al intentar acceder a un sitio web usando por ejemplo www.dominio.com o solo dominio.com.
Para realizar esto, simplemente desde el servidor debemos utilizar el siguiente comando:
Una ves que usemos este comando, certbot nos pedirá incluir en nuestros registros DNS un texto especifico para validar que efectivamente somos nosotros los dueños del dominio. Una ves que hicimos esto entonces se emitirán los certificados.
El texto a agregar en nuestros DNS es del tipo TXT con el texto: _acme-challenge.domain.com y el valor que nos muestre certbot en la pantalla, por ejemplo:
AJS6dkfjskAasidju_aksjdhauOIsyh-asjkYasdK39
Es un valor inventado por razones de seguridad 😀
Es importante luego de esto configurar apache, dovecot, postfix o los servicios que usemos para que apunten a estos nuevos certificados.
Hacemos click en Rotulación de etiquetas y agregamos una nueva entrada:
Volvemos a la SPRO y vamos a:
Creamos una nueva implementación:
Implementamos el método CHECK_ADD_ON_ACTIVE:
Volvemos a la SPRO:
Creamos una nueva implementación:
Creamos el filtro:
Creamos un grupo de función y le creamos una DynPro (La que especificamos anteriormente)
En la dynpro Agregamos el campo que queremos mostrar:
Implementamos el método GET_TAXI_SCREEN de la BADI:
En este punto ya podríamos ir a la transacción XD01 / 02 / 03 y ver nuestro campo.
Ahora hay que agregar una APPEND STRUCTURE a la tabla KNA1.
Ahora hay que hacer que en modo visualización el campo aparezca no editable, para esto vamos al grupo de función que creamos y agregamos el siguiente código:
Ahora debemos agregar la lógica para cargar y guardar el dato de nuestro campo Z.
Cargar:
Guardar:
Implementamos el método de la BADI (La de la subscreen).
Vamos a la TRX SSC4 y agregamos una nueva entrada:
Completamos los siguientes datos según nuestra necesidad:
Grabamos.
Vamos a la TRX SCCLN y la ejecutamos como test.
Nos muestra el resultado:
Si esta todo bien entonces podemos ejecutarlo sin modo test.
Si al ejecutarlo nos da el siguiente error:
Puede ser que haya quedado un registro en la tabla LMSEMAPHORE, de alguna ejecución anterior que no termino, podemos borrarlo de la tabla y volver a ejecutarlo o buscar la ejecución previa y terminarla.
El generador de tablas de mantenimiento o del ingles Table Maintenance Generator, sirve para crear vistas de actualización de tablas, las cuales son servirán entre otras cosas para ingresar datos a nuestras tablas en el sistema.
Lo primero que tenemos que tener es una tabla transparente. Para nuestro ejemplo usaremos la siguiente.
El próximo paso es la creación de la vista de actualización en si, para esto vamos al siguiente menu.
Nos aparecerá la siguiente ventana
El primer paso es ingresar el grupo de autorización, esto nos servirá para restringir el acceso, para nuestro caso, como no necesitamos esto ingresamos &NC&, que significa, Sin grupo de autorización.
En function group, ingresamos el nombre que le vamos a dar al Function Group, una vista de actualization de tabla, básicamente por detrás es un grupo de función, yo por lo general uso el mismo nombre que de la tabla. En este caso ZAEROLINEAS.
En Maintenance Type, tenemos dos opciones: 1) One step: Nuestra vista de actualización de tabla constara de solo una pantalla 2) Two step: Nuestra vista de actualización de tabla constara de dos pantallas. Para este caso seleccionaremos One Step.
Siguiente, hacemos click en Find Scr. Number(s)
Automáticamente nos completara lo siguiente
Finalmente hacemos click en la Hoja blanca
Nos pedirá ingresar un paquete o objeto local, en el caso que seleccionemos paquete también nos pedirá una orden de transporte.
Cuando termine, nos debería mostrar el siguiente mensaje.
A este punto ya tenemos la vista de actualización de tabla creada, si vamos a la transacción SM30 podemos usarla.
Aca ingresamos el nombre de nuestra vista de actualización de tabla y dependiendo de que queremos hacer, podemos hacer click en Display o Maintain. Para continuar con nuestro ejemplo, le hacemos click en Maintain.
Nos debería aparecer una pantalla similar a la siguiente.
Al hacer click en New Entries se nos habilitara la opción de ingresar datos. Si nos posicionamos en la celda Airline (La primera), vemos que nos da la opción de seleccionar un Match Code.
Sin embargo, si nos paramos en la siguiente columna, vemos que no nos muestra el icono para seleccionar un valor.
Hay varias formas de agregar el Match Code, pero la mas simple en mi opinion. es buscar un Search Help que ya exista para ese campo. En este caso por ejemplo, Sabemos que el nombre de la aerolínea se guarda en la tabla SCARR, entonces lo que podríamos hacer, es ir a la transacción SE11 a la parte de Search Help y buscar algo similar a *SCARR*
Hacemos click en el Match Code o apretamos F4 (Que es un atajo) y vemos que automáticamente nos completa el campo a H_SCARR, si con este valor seleccionado le damos click a display. Vemos que esta ayuda de búsqueda, contiene los campos que queremos.
Ya con este nombre, entonces volvemos a la SE11 a nuestra tabla, y vamos a la solapa Input/Help Check
Nos paramos en la linea del campo a la que queremos agregarle el Match Code en la vista de mantenimiento y hacemos click en el botón “Search Help” (Tenemos que estar en modo edición).
Nos aparecerá la siguiente pantalla donde ingresamos la ayuda de búsqueda que encontramos en el paso anterior.
En la siguiente pantalla verificamos que los campos de la ayuda de búsqueda coincidan con los de nuestra tabla y hacemos click en Copy.
Nuestra tabla ahora debería verse algo similar a lo siguiente.
Ahora debemos activar nuestra tabla haciendo click en el botón de activar. Con la tabla activa, ahora debemos regenerar nuestra vista de actualización de tablas, dado que si ingresamos ahora, podemos ver que no cambio nada.
Para regenerarla, debemos volver al menu.
Una buena practica, antes de regenerar nuestra vista de actualización de tabla, es revisar si esta tiene eventos. Los eventos son acciones que podemos realizar en ciertos momentos en nuestra vista de actualización, como por ejemplo para validar los datos ingresados. Si nosotros borramos la vista de actualización de tabla corremos el riesgo de borrar los eventos también, por lo cual nos conviene hacernos un backup por las dudas. Para esto vamos al siguiente menu.
Si nos aparece vació, como en el ejemplo de abajo, entonces la podemos regenerar tranquilamente.
En el caso de que haya algún evento, debemos entrar al mismo y copiarnos el código, haciendo click en el botón que aparecerá en la columna “Editor” de la captura de arriba.
Para regenerar nuestra vista, simplemente hay que hacer click en el siguiente botón.
Nos aparecerá la siguiente ventana con opciones a seleccionar de lo que queremos borrar. Si sabemos en que sección se encuentra lo que modificamos podemos seleccionar específicamente una. Para este caso seleccionamos todas.
Ahora volveremos a la pantalla donde debemos volver a generar la vista de actualización al igual que lo hicimos la primera ves.
Con nuestra vista de actualización regenerada, podemos volver a la SM30 (Por las dudas se recomienda salir de la transacción y volver a entrar si no salieron ya) e ingresar de nuevo a nuestro objeto.
Al ingresar de nuevo e ir a agregar una nueva entrada podemos ver que ahora nos aparece el Match Code.
Tambien podemos ver que si seleccionamos un valor del nuevo Match Code automáticamente nos llena el primero de la tabla.
Por ultimo, supongamos que por alguna razón, queremos que el campo Airline URL quede griseado, para hacer esto, primero tenemos que volver a la SE11 a nuestra tabla e ir de nuevo al Table Maintenance Generator. Y vamos al menu Environment–>Modification–>Maintenance Screen.
Nos aparecerá la siguiente pantalla en la que hacemos doble click en la screen a modificar.
Esto nos llevara al screen painter, en donde hacemos click en el botón Layout.
Se nos abrirá la siguiente ventana. En donde vemos los campos que se muestran en la pantalla de la vista de actualización de tablas.
Hacemos doble click en el campo marcado en la captura de arriba y se nos debería abrir otra ventana, en donde debemos des-tildar la opción Input Field, en el tab Program, para hacer que este campo sea NO editable.
Podemos ver que el campo se encuentra griseado, hacemos click en activar y back.
Si ahora volvemos a la transacción SM30 e ingresamos de nuevo para agregar un valor nuevo a nuestra tabla, veremos que el campo se encuentra griseado. (Es posible que tengan que salir y volver a entrar a la SM30 si ya la tenían abierta).
Uno de los problemas que encontré al querer usar mi Raspberry PI 4 (con Ubuntu) es que al desconectarle monitor, teclado y mouse, lo que se le llama headless, es que linux no creaba el entorno gráfico.
Después de mucho googleo encontré una forma que les voy a compartir.
Instalar el desktop que mas nos guste, si estan usando Ubuntu Desktop para ARM entonces esto ya lo tienen.
Instalar el paquete XRDP usando “sudo apt install xrdp”
Agregar el usuario al grupo usando “sudo adduser xrdp ssl-cert”
Reiniciamos el servicio para que tome los cambios usando “sudo systemctl restart xrdp”
Finalmente para conectarnos tenemos que usar algún cliente de RDP como nRemoteNG (si están en windows)
Creamos una nueva conexión y le damos un nombre
Ingresamos el Hostname, nombre de usuario y password que usamos para logearnos en nuestro Raspberry. Tambien nos aseguramos de que este seleccionado RDP como protocolo.
Hacemos doble click en la nueva entrada para logearnos y nos debería aparecer la siguiente pantalla
Ya podemos usar nuestro Raspberry desde el entorno gráfico normalmente.
Al igual que cuando creamos la vista CDS, para crear una table function debemos crear un data definition como hicimos antes, pero al momento de llegar al template seleccionamos “Define Table Function with parameters”
Al hacer click en finish nos aparecerá el template seleccionado el cual debemos completar para que quede similar a lo siguiente:
@EndUserText.label: 'Table function para vuelos'
define table function ZTF_VUELOS
with parameters
@Environment.systemField: #CLIENT
client : mandt,
returns {
client : abap.clnt;
carrid : s_carr_id;
connid : s_conn_id;
fldate : s_date;
carrname : s_carrname;
URL : s_carrurl;
price : s_price;
currency : s_currcode;
passname : s_passname;
}
implemented by method zcl_vuelos2=>obtener_datos_pasajeros;
Vemos que al final le estamos especificando la clase (ZCL_VUELOS2) y el método (obtener_datos_pasajeros) que vamos a llamar.
El próximo paso será crear esta clase y método, para esto hacemos click derecho sobre nuestro package o objeto local y seleccionamos crear una clase.
Ingresamos un nombre (El que usamos en la Table function) y descripción.
De nuevo seleccionamos una orden de transporte y le damos click a Finish o si es un objeto local directamente hacemos click en finish.
Nos creara el template que se vera similar a:
Adaptamos la clase para que tenga la lógica que nosotros queramos, por ejemplo:
CLASS zcl_vuelos2 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES : if_amdp_marker_hdb.
CLASS-METHODS : obtener_datos_pasajeros FOR TABLE FUNCTION ZTF_VUELOS.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_vuelos2 IMPLEMENTATION.
METHOD obtener_datos_pasajeros BY DATABASE FUNCTION FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING scarr sflight sbook.
RETURN
SELECT a.mandt AS client, a.carrid AS carrid, a.connid AS connid, a.fldate AS fldate,
b.carrname AS carrname, b.URL as URL, a.price AS price, a.currency AS currency,
c.passname AS passname FROM sflight AS a
INNER JOIN scarr AS b
ON a.carrid = b.carrid
INNER JOIN sbook AS c
ON a.carrid = c.carrid AND
a.connid = c.connid AND
a.fldate = c.fldate
WHERE a.mandt = c.mandt;
ENDMETHOD.
ENDCLASS.
Ahora debemos creamos una vista CDS que utilice nuestra table function. Para esto, como hicimos antes nos creamos una vista CDS.
Nuestra vista debería ser algo similar a esto:
Lo importante a ver acá, es que estamos haciendo el SELECT desde la Table Function (SELECT FROM ZTF_VUELOS ).
@AbapCatalog.sqlViewName: 'ZCDS_TF_DATOS_V'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Datos de pasajeros usando TF'
define view ZCDS_TF_DATOS as select from ZTF_VUELOS ( client : $session.client ) {
carrid,
connid,
fldate,
carrname,
URL,
@Semantics.amount.currencyCode: 'CurrencyCode'
price,
@Semantics.currencyCode
cast ('USD' as abap.cuky) as CurrencyCode,
currency,
passname
}
Una ves con nuestra nueva vista creada, la podemos consultar como hicimos antes desde la SE16. Pero también lo que podemos hacer es ponerle un breakpoint en la clase que creamos.
Para hacer esto, en eclipse, vamos a la clase que creamos y hacemos doble click donde esta marcado en la captura de abajo. Nos debería aparecer un puntito en color verde si el breakpoint esta activo.
Una ves con el breakpoint activo, podemos ejecutar la vista desde la SE16 y se nos debería activar el debugger en eclipse.
Para ver mejor por debug podemos cambiar el código por:
CLASS zcl_vuelos2 DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES : if_amdp_marker_hdb.
CLASS-METHODS : obtener_datos_pasajeros FOR TABLE FUNCTION ZTF_VUELOS.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_vuelos2 IMPLEMENTATION.
METHOD obtener_datos_pasajeros BY DATABASE FUNCTION FOR HDB
LANGUAGE SQLSCRIPT
OPTIONS READ-ONLY
USING scarr sflight sbook.
/* RETURN */
lt_datos = SELECT a.mandt AS client, a.carrid AS carrid, a.connid AS connid, a.fldate AS fldate,
b.carrname AS carrname, b.URL as URL, a.price AS price, a.currency AS currency,
c.passname AS passname FROM sflight AS a
INNER JOIN scarr AS b
ON a.carrid = b.carrid
INNER JOIN sbook AS c
ON a.carrid = c.carrid AND
a.connid = c.connid AND
a.fldate = c.fldate
WHERE a.mandt = c.mandt;
RETURN :lt_datos;
ENDMETHOD.
ENDCLASS.
En la imagen de abajo podemos ver el breakpoint en la línea 22, a la derecha del código podemos ver nuestra variable lt_datos donde se guarda el resultado de la consulta y en la parte de inferior de la pantalla podemos ver el contenido de la tabla interna.
Tambien al igual que con una vista CDS común, la podemos usar desde un reporte ABAP:
SELECT * FROM ZCDS_TF_DATOS( pcarrid = 'AA', pconnid = '0017', pfldate = @lv_fecha )
INTO TABLE @DATA(lt_datos2).
IF sy-subrc = 0.
ENDIF.
Tambien podemos usar un ALV IDA para mostrar los datos:
REPORT zida_cds.
data: lo_exc type ref to cx_salv_function_not_supported.
try.
cl_salv_gui_table_ida=>create_for_cds_view( 'ZCDS_VUELOS' )->fullscreen( )->display( ).
catch cx_salv_function_not_supported into lo_exc.
message lo_exc type 'I'.
endtry.