Smartforms

Son objetos de SAP que se utilizan para crear documentos que necesitan ser impresos, visualizados por pantalla o enviados por correo electrónico.

El modelo smartform

Un formulario Smartform está compuesto por dos objetos:

  • El programa impresor: que es donde se definen los datos que se imprimirán en el formulario.
  • Formulario: que es donde se define el layout o disposición de los datos.

Transacciones para la creación de formularios

Se utilizan las siguientes transacciones.

Smartforms para crear el layout o disposición de los datos.

Smartstyles para crear los estilos que utilizaremos en el smartform

SE78 Agregar imagen al formulario

SE73 Para subir fuentes, crear códigos de barras que no estén en SAP, para utilizarlos en los formularios.

SE38 para crear el programa impresor

Creación de formularios

A continuación se indica paso a paso como se tiene que realizar la creación de un formulario en SAP.

Creación de un estilo

Todos los formularios en SAP tienen que utilizar un estilo puede utilizarse uno estándar de SAP o crearte uno propio.

En los estilos se definen formatos de párrafo que contienen información sobre sangrías, espaciados, configuración de fuentes, texto, colores etc…

Vamos a la transacción Smartstyles y creamos un estilo, inicialmente sale de la siguiente manera

s1

  • Creación de un Párrafo

Lo primero que se tiene que hacer es crear los tipos de párrafos que vamos a utilizar, con lo que pulsaremos sobre el botón derecho del ratón en Form.párrafo.

s2En la primera pestaña se puede definir alineación, sangría, interlineado

s3Se podrán utilizar diferentes tipos de medidas, pero se aconseja utilizar CM o MM

  1. En la pestaña FONT se indicará la fuente del parrafo
  2. En la pestaña TABULADORES podremos crear tabuladores para comenzar los textos en distintas columnas de un párrafo
  3. En la pestaña NUMERACIÓN y ESQUEMA se utilizarán para crear esquemas
  • Creación de un caracter

Se pueden crear caracteres para indicar que vamos a imprimir un código de barras, o si queremos un tamaño diferente al tamaño de la fuente del párrafo que hemos creado.

En este ejemplo se indica que el carácter es un código de barras (Transacción SE73)

s4Por último tendremos que definir los datos de cabecera, para tener el estilo creado.

s5

Creación del Formulario

Nos vamos a la transacción smartforms y creamos el formulario zformulario.

Definición de los atributos del formulario

Aquí ponemos en el formato de salida, el estilo que hemos definido anteriormente.

s6Definición de las variables de entrada al formulario

En interfase del formulario especificaremos las variables, estructuras y tablas que recibe como entrada un formulario.

s7Definiciones globales

En esta sección indicaremos las variables locales con la que trabajaremos en el formulario.

  • Datos globales: aquí indicaremos todas las variables, constantes, estructuras, tablas internas que utilizaremos en el formulario
  • Tipos: Aquí declararemos los tipos que utilizaremos en el formulario
  • Símbolos de campo: Aquí se declararan los Field-symbol que utilizaremos en el formulario
  • Inicialización: Aquí declaramos el código que necesita ejecutar el formulario, incluidas llamadas a subrutinas
  • Rutinas FORM: aquí codificamos las subrutinas que se hayan declarado en la pestaña inicialización.
  • Campo moneda/cantidad: aquí indicaremos los campos importe.

Elementos que componen un formulario

A continuación se indican los componentes de un formulario.

Páginas

Un formulario consiste en una o más páginas, la primera página ya existe cuando se crea un formulario, lo normal es que se cambie este nombre.

s8

  • En opciones de salida, indicaremos si queremos que la página este en vertical o apaisado (horizontal)
  • En Fondo, indicaremos una imagen de fondo para el formulario (marca de agua)

s9Ventanas

Son el área de salida de datos, que mostraremos dentro de las páginas en el formulario, existen varios tipos de ventanas, tendrás la principal que será el main y luego se harán ventanas auxiliares.

s10

  • Opciones de salida, se indica las dimensiones de la ventana, posición en la página, marcos y sombras
  • Condiciones, se indican las condiciones para la visualización de la ventana, y también se podrá indicar los siguientes casos.

s11Textos

Aquí crearemos los textos de salida del formulario, en el que podremos texto y mostraremos los valores de salida de las variables definidas en el formulario, poniéndolas entre &.

s12

  • Opciones de salida, indicaremos el estilo.
  • Condiciones, declararemos las condiciones de visualización del texto.

Tablas

Se crearán para mostrar los datos que tengas almacenados en tablas internas, en el botón Details indicaremos las dimensiones las columnas.

s13En la pestaña datos indicaremos la tabla interna que vamos a utilizar.

s14En la pestaña cálculos se pueden hacer el total, valor medio o cantidad sobre los campos que estamos recorriendo.

Área principal, crearemos textos para cada una de las columnas.

s15Gráficos

Podremos agregar gráficos que previamente hayamos subido en la transacción SE78, solo se admitirán gráficos en formato .BMP o TIF.

s16

TAD Lista

Como soy ingeniero técnico informático, voy a demostrar que se pueden hacer estructuras de datos en ABAP.

A continuación voy a mostrar como hacer un TAD Lista.

Programa de control

Desde el programa de control, instanciaremos la clase lista y la utilizaremos

t1

t2

Creación de la clase Lista

A continuación voy a mostrar los atributos de la clase.

Atributos

  • Long que nos indicará la logitud de la lista
  • Container en donde almacenaremos la información

t3

Métodos

A continuación voy a mostrar los métodos de la clase.

t4

Implementación de los métodos

Constructor

t6

t5

Get_lenght

t7

Consult

t8

t9

Insert

t10

t11

Set_type_list

t12

Isempty

t13

t14

Search

t15

t16

t17

Modify

t18

t19

Delete

t20

Refresh

t21

Optimización del código Abap IV

Este documento pretender ser una ayuda de como optimizar el código de los programa ABAP/4.

Primero se explicará cómo se tienen que diseñar los programas y seguidamente que instrucciones y como utilizarlas.

Líneas generales para conseguir un buen diseño.

  1. Evitar hard-code ya que requiere la modificación del código fuente cada vez que cambian los datos
  2. Evitar códigos muertos
  3. Documentación de los programas, tanto en el código como en los diseños
  4. Pruebas unitarias
  5. Estructuración de los programas, para que las variables únicamente se carguen en memoria cuando se vayan a utilizar.
  • Se tienen que utilizar lo mínimo posible el uso de variables globales.

Instrucciones ABAP

A continuación se van a detallar como se deberían utilizar cada una de las sentencias Abap, para que el código sea óptimo.

Accesos a la base de datos mediante sentencias Select

select

Clausula Where

No se puede  construir sentencias sin la clausula Where.

where

Selección de campos

Siempre se tendrá que poner los campos a los que se quiere acceder, no se debería utilizar *, salvo en caso necesarios.

seleccion

Operaciones con tablas internas

– Copiar registros de una tabla a otra

copiar tabla

– Borrar registros de una tabla

borrar tabla

– Modificar registros de una tabla

modificar tabla

Loop encadenados

Para modificar una tabla que necesite buscar datos en otra y se produzcan bucles anidados se tendrá que hacer por búsqueda binaria

Búsqueda binaria

Integración con otros sistemas

Integración con otros sistemas

A continuación voy a indicar como hacer la integración con otros sistemas en este caso pondré como ejemplo la integración entre SAP R/3 y CRM Dynamics, mediante un Web services RES.

52

La comunicación entre los sistemas será mediante XML, pongo un ejemplo de un XML

<?xml version=»1.0″?>
<ProductoR3Config xmlns:xsi=»http://www.w3.org/2001/XMLSchema-instance» xmlns:xsd=»http://www.w3.org/2001/XMLSchema» xmlns=»http://crm.dynamics.unedisa.neoris.es/integracion/v1-0/»>
<CodigoProductoR3>SDLGASTOS81</CodigoProductoR3>
<Nombre>Nombre a enviar</Nombre>
<CreatedOn>2009-12-28T15:39:32</CreatedOn>
</ProductoR3Config>

Código para realizar la comunicación entre sistemas

Personalmente me gusta programar con clases, así que pondre como ejemplo la siguiente clase:

En este caso no declararemos ningún atributo:

53

Vamos a crear los siguientes métodos:

54

Muestro como va quedar la sección pública de la clase:

class ZCONEXION_CRM_PETCRM definition
public
create public .

*»* public components of class ZCONEXION_CRM_PETCRM
*»* do not include other source files here!!!
public section.

methods CONSTRUCTOR .
methods GET_URL
importing
!IM_IDENTIFICADOR type ANY
exporting
!EX_URL type STRING .
methods CREAR_CLIENTE_HTTP
importing
!IM_URL type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_VERSION
importing
!IM_VERSION type I
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_POST
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_GET
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods SET_DATOS_GET
importing
!IM_DATOS type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods CONVERTIR_FORMATO_GET
importing
!IM_ESTRUCTURA type ANY
!IM_NOMBRE_ESTRUCTURA type STRING
exporting
!EX_CONVERSION type STRING .
methods CONVERTIR_FORMATO_POST
importing
!IM_ESTRUCTURA type ANY
!IM_NOMBRE_ESTRUCTURA type STRING
exporting
!EX_CONVERSION type STRING .
methods SET_DATOS_CABECERA
importing
!IM_DATOS_CABECERA type TIHTTPNVP
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods RELLENAR_CABECERA
importing
!IM_NOMBRE type IHTTPNAM
!IM_VALOR type IHTTPVAL
exporting
!EX_DATOS_CABECERA type TIHTTPNVP .
methods ENVIAR_DATOS
importing
!IM_CLIENTE_HTTP type ref to IF_HTTP_CLIENT
!IM_DATO type ANY
exporting
!EX_RESULTADO type STRING .
methods SET_DATOS_BODY
importing
!IM_DATOS_BODY type STRING
exporting
!EX_CLIENTE_HTTP type ref to IF_HTTP_CLIENT .
methods GET_CLAVE
importing
!IM_NOMBRE_SO10 type TDOBNAME
exporting
!EX_CLAVE type IHTTPVAL .
methods GET_LONGITUD
importing
!IM_XML type STRING
exporting
!EX_LONGITUD type IHTTPVAL .

En la sección pública podemos ver los datos de entrada y salida de los métodos.

Método para obtener la URL

Se tendrá que tener una tabla de parámetros, en la que pondremos la URL de conexión contra el Web services.

METHOD get_url.

CONSTANTS: lc_clase   TYPE kschl          VALUE ‘WWW’,
lc_codigo TYPE zcm_codigo_iva VALUE ‘W’.

SELECT SINGLE valores INTO ex_url
FROM  zcm_parametros
WHERE kschl  EQ lc_clase
AND   codigo EQ lc_codigo.

ENDMETHOD.

Crear cliente http

Lo primero que se tiene que hacer es crear un cliente http, que es el que nos proporcionará las herramientas de conexión.

  • Datos de entrada al método

IM_URL   Importing           Type      STRING

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

METHOD CREAR_CLIENTE_HTTP.

CALL METHOD cl_http_client=>create_by_url
EXPORTING
url                = im_url
IMPORTING
client             = ex_cliente_http
EXCEPTIONS
argument_not_found = 1
plugin_not_active  = 2
internal_error     = 3
OTHERS             = 4.

ENDMETHOD.

Indicar Versión

Se tendrá que poner la versión del protolo http:

  • Datos de entrada al método

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

IM_VERSION                        Importing             Type      I

METHOD set_version.

CONSTANTS: lc_cero TYPE i VALUE 0,
lc_uno  TYPE i VALUE 1.

IF lc_cero EQ im_version.
CALL METHOD ex_cliente_http->request->set_version( if_http_request=>co_protocol_version_1_0 ).
ELSEIF lc_uno EQ im_version.
CALL METHOD ex_cliente_http->request->set_version( if_http_request=>co_protocol_version_1_1 ).
ENDIF.» lc_cero EQ im_version.

ENDMETHOD.

Envío datos mediante POST

Cuando no se envían los datos por la URL, sino que se envía mediante un XML.

  • Datos de entrada al método

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

method SET_POST.

CALL METHOD ex_cliente_http->request->set_method( if_http_request=>co_request_method_post ).

endmethod.

Envío de datos mediante GET

Este método envia las variables dentro de la propia URL (dirección) de la página, concatenadas(unidas) por ampertands(&)

  • Datos de entrada al método

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

method SET_GET.

CALL METHOD ex_cliente_http->request->set_method( if_http_request=>co_request_method_get ).

endmethod.

Rellenar GET

Aquí se rellena mediante un String, pongo un ejemplo: im_datos = ‘codigopostal=28030&grupoproductoid=ae90b27f-e9e7-e311-a548-6c3be5be5ec4&codigopais=ES&codigoprovincia=28’

  • Datos de entrada al método

IM_DATOS            Importing           Type      STRING

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

METHOD set_datos_get.

cl_http_utility=>set_query( request = ex_cliente_http->request query = im_datos ).

ENDMETHOD.

Conventir formato GET

Yo en estos casos tengo declarada una estructura en la SE11, con los campos a enviar en el GET.

  • Datos de entrada al método

IM_ESTRUCTURA                          Importing           Type      ANY

IM_NOMBRE_ESTRUCTURA         Importing            Type      STRING

EX_CONVERSION                          Exporting            Type      STRING

METHOD convertir_formato_get.

TYPE-POOLS: slis.

CONSTANTS: lc_af    TYPE string VALUE ‘<‘,
lc_cf    TYPE string VALUE ‘>’,
lc_ac    TYPE string VALUE ‘</’,
lc_igual TYPE string VALUE ‘=’,
lc_amp   TYPE string VALUE ‘&’.

FIELD-SYMBOLS: <ls_estructura> TYPE ANY,
<lt_table>          TYPE STANDARD TABLE.

DATA: ls_estructura  TYPE REF TO data,
lt_table       TYPE REF TO data.
DATA: lv_xml_out     TYPE string.
DATA: lv_sobrante    TYPE string,
lv_total       TYPE string,
lv_corte       TYPE string,
lv_corte_final TYPE string,
lv_valor       TYPE string.
DATA: lv_name        TYPE dd02l-tabname,
lt_fieldcat    TYPE slis_t_fieldcat_alv,
ls_fieldcat    TYPE slis_fieldcat_alv.
DATA: lv_contador    TYPE i VALUE 0.

CREATE DATA ls_estructura TYPE (im_nombre_estructura).
CREATE DATA lt_table TYPE STANDARD TABLE OF (im_nombre_estructura).

ASSIGN ls_estructura->* TO <ls_estructura>.
ASSIGN lt_table->* TO <lt_table>.

<ls_estructura> = im_estructura.

APPEND <ls_estructura> TO <lt_table>.

CALL TRANSFORMATION (‘ID’)
SOURCE tab = <lt_table>
RESULT XML lv_xml_out.

lv_corte = im_nombre_estructura.

TRANSLATE lv_corte TO UPPER CASE.
CONCATENATE lc_af lv_corte lc_cf INTO lv_corte.

SPLIT lv_xml_out AT lv_corte INTO lv_sobrante lv_total.

lv_name = im_nombre_estructura.

CALL FUNCTION ‘REUSE_ALV_FIELDCATALOG_MERGE’
EXPORTING
i_structure_name       = lv_name
CHANGING
ct_fieldcat            = lt_fieldcat
EXCEPTIONS
inconsistent_interface = 1
program_error          = 2
OTHERS                 = 3.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.» sy-subrc <> 0.

LOOP AT lt_fieldcat INTO ls_fieldcat.
CLEAR: lv_corte,
lv_corte_final,
lv_sobrante,
lv_valor.

CONCATENATE lc_af ls_fieldcat-fieldname lc_cf INTO lv_corte.
CONCATENATE lc_ac ls_fieldcat-fieldname lc_cf INTO lv_corte_final.

SPLIT lv_total AT lv_corte       INTO lv_sobrante lv_total.
SPLIT lv_total AT lv_corte_final INTO lv_valor lv_total.

IF lv_contador EQ 0.
CONCATENATE ls_fieldcat-fieldname lc_igual lv_valor INTO ex_conversion.
ELSE.
CONCATENATE ex_conversion lc_amp ls_fieldcat-fieldname lc_igual lv_valor INTO ex_conversion.
ENDIF.» lv_contador EQ 0.

ADD 1 TO lv_contador.
ENDLOOP.» LOOP AT lt_fieldcat INTO ls_fieldcat.

ENDMETHOD.

Convertir formato POST

En este caso lo que vamos hacer es convertir los campos de una estructura en la SE11 en un XML.

  • Datos de entrada al método

IM_ESTRUCTURA               Importing           Type      ANY

IM_NOMBRE_ESTRUCTURA         Importing           Type      STRING

EX_CONVERSION               Exporting            Type      STRING

METHOD convertir_formato_post.

FIELD-SYMBOLS: <ls_estructura> TYPE ANY,
<lt_table> TYPE STANDARD TABLE.

DATA: ls_estructura TYPE REF TO data,
lt_table      TYPE REF TO data.
DATA: lv_xml_out    TYPE string.

CREATE DATA ls_estructura TYPE (im_nombre_estructura).
CREATE DATA lt_table TYPE STANDARD TABLE OF (im_nombre_estructura).

ASSIGN ls_estructura->* TO <ls_estructura>.
ASSIGN lt_table->* TO <lt_table>.

<ls_estructura> = im_estructura.

APPEND <ls_estructura> TO <lt_table>.

CALL TRANSFORMATION (‘ID’)
SOURCE tab = <lt_table>
RESULT XML ex_conversion.

ENDMETHOD.

Set datos cabecera

  • Datos de entrada al método

IM_DATOS_CABECERA    Importing           Type      TIHTTPNVP

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

METHOD set_datos_cabecera.

CALL METHOD ex_cliente_http->request->set_header_fields
EXPORTING
fields = im_datos_cabecera.

ENDMETHOD.

Rellenar la cabecera

  • Datos de entrada al método

IM_NOMBRE        Importing           Type      IHTTPNAM

IM_VALOR            Importing           Type      IHTTPVAL

EX_DATOS_CABECERA     Exporting            Type      TIHTTPNVP

METHOD rellenar_cabecera.

DATA: ls_cabecera TYPE ihttpnvp.

ls_cabecera-name  = im_nombre.
ls_cabecera-value = im_valor.

APPEND ls_cabecera TO ex_datos_cabecera.

ENDMETHOD.

Enviar los datos

  • Datos de entrada al método

IM_CLIENTE_HTTP             Importing           Type Ref To       IF_HTTP_CLIENT

IM_DATO               Importing           Type      ANY

EX_RESULTADO   Exporting            Type      STRING

METHOD enviar_datos.

CONSTANTS: lc_error_envio TYPE string      VALUE ‘Error de envío’,
lc_uno         TYPE zflag       VALUE ‘1’,
lc_cero        TYPE zflag       VALUE ‘0’,
lc_error       TYPE zflag_error VALUE ‘E’,
lc_correcto    TYPE zflag_error VALUE ‘C’.

DATA: lv_code          TYPE sysubrc,
lv_codigo        TYPE string,
lv_errortext     TYPE string.
DATA: lv_rango         TYPE numc10,
ls_log_envio     TYPE zlog_crm,
ls_log_recepcion TYPE zlog_crm.
DATA: lv_http_rc       TYPE sy-subrc.

CALL FUNCTION ‘NUMBER_GET_NEXT’ » número para el Log
EXPORTING
nr_range_nr                   = ’01’
object                        = ‘ZCRM_LOG’
quantity                      = ‘1’
IMPORTING
number                        = lv_rango.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

ls_log_envio-id_numero     = lv_rango.
ls_log_envio-fecha         = sy-datum.
ls_log_envio-hora          = sy-uzeit.
ls_log_envio-flag          = lc_cero.
ls_log_envio-identificador = im_dato.

CALL METHOD im_cliente_http->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state         = 2
http_processing_failed     = 3
http_invalid_timeout       = 4
OTHERS                     = 5.
IF sy-subrc <> 0.
ex_resultado = lc_error_envio.
ENDIF.

CALL METHOD im_cliente_http->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state         = 2
http_processing_failed     = 3
OTHERS                     = 4.

IF sy-subrc = 0.
ex_resultado = im_cliente_http->response->get_cdata( ).
im_cliente_http->response->get_status( IMPORTING code = lv_http_rc ).
IF lv_http_rc <> 200.» Error de recepción
ls_log_envio-flag_error    = lc_correcto.
CONCATENATE ‘Envío correcto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.

ls_log_recepcion-id_numero     = lv_rango.
ls_log_recepcion-fecha         = sy-datum.
ls_log_recepcion-hora          = sy-uzeit.
ls_log_recepcion-flag          = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error    = lc_error.
CONCATENATE ‘Respuesta CRM: datos incorrectos en’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.
ELSE.» Todo correcto
ls_log_envio-flag_error    = lc_correcto.
CONCATENATE ‘Envío correcto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.

ls_log_recepcion-id_numero     = lv_rango.
ls_log_recepcion-fecha         = sy-datum.
ls_log_recepcion-hora          = sy-uzeit.
ls_log_recepcion-flag          = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error    = lc_correcto.
CONCATENATE ‘Recepción correcta de:’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.
ENDIF.» lv_http_rc <> 200.
ELSEIF sy-subrc <> 0.» error de envío y recepción
CALL METHOD im_cliente_http->get_last_error
IMPORTING
code    = lv_code
MESSAGE = lv_errortext.

lv_codigo = lv_code.

CONCATENATE ‘communication_error : ‘ lv_codigo ‘message: ‘ lv_errortext INTO ex_resultado SEPARATED BY space.

ls_log_envio-flag_error    = lc_error.
CONCATENATE ‘Envío incorrecto de:’ im_dato INTO ls_log_envio-descripcion SEPARATED BY space.

ls_log_recepcion-id_numero     = lv_rango.
ls_log_recepcion-fecha         = sy-datum.
ls_log_recepcion-hora          = sy-uzeit.
ls_log_recepcion-flag          = lc_uno.
ls_log_recepcion-identificador = im_dato.
ls_log_recepcion-flag_error    = lc_error.
CONCATENATE ‘Recepción incorrecta de:’ im_dato INTO ls_log_recepcion-descripcion SEPARATED BY space.

ENDIF.» sy-subrc = 0.

INSERT zlog_crm FROM ls_log_envio.
INSERT zlog_crm FROM ls_log_recepcion.

COMMIT WORK AND WAIT.

CALL METHOD im_cliente_http->close( ).

ENDMETHOD.

Set datos body

  • Datos de entrada al método

IM_DATOS_BODY              Importing           Type      STRING

EX_CLIENTE_HTTP             Exporting            Type Ref To       IF_HTTP_CLIENT

METHOD set_datos_body.

CALL METHOD ex_cliente_http->request->set_cdata
EXPORTING
data = im_datos_body.

ENDMETHOD.

Get longitud

Método muy importante ya que tendremos que saber la longitud del XML cuando digamos que lo enviamos en formato UTF-8, ya que sino se indica la logitud abra problemas en la conversión del formato.

  • Datos de entrada al método

IM_XML  Importing           Type      STRING

EX_LONGITUD     Exporting            Type      IHTTPVAL

METHOD get_longitud.

DATA: lv_xml_change TYPE xstring.
DATA: cl_cvto_utf8  TYPE REF TO cl_abap_conv_out_ce.
DATA: lv_long       TYPE i VALUE 0.

cl_cvto_utf8 = cl_abap_conv_out_ce=>create( encoding = ‘UTF-8’ ).
cl_cvto_utf8->write( data = im_xml ).
lv_xml_change = cl_cvto_utf8->get_buffer( ).
lv_long = XSTRLEN( lv_xml_change ).
MOVE lv_long TO ex_longitud.

ENDMETHOD.

Función de llamada al Web services

TYPE-POOLS: truxs.

CONSTANTS: lc_nombre_estructura TYPE string   VALUE ‘zcm_petcrm’,
lc_version_uno       TYPE i        VALUE 1,
lc_autorizar         TYPE ihttpnam VALUE ‘Authorization’,
lc_content_valor     TYPE ihttpval VALUE ‘text/xml; charset=utf-8’,
lc_content_type      TYPE ihttpnam VALUE ‘Content-Type’,
lc_content_lenght    TYPE ihttpnam VALUE ‘Content-Length’,
lc_so10              TYPE tdobname VALUE ‘ZCLAVE_CRM’,
lc_estado            TYPE kschl    VALUE ‘LINE’,
lc_activo            TYPE char200  VALUE ‘ON’.

DATA: carga_materiales TYPE REF TO zcarga_materiales_petcrm.
DATA: conexion         TYPE REF TO zconexion_crm_petcrm.
DATA: lv_cliente       TYPE REF TO if_http_client.
DATA: lv_url           TYPE string.
DATA: ls_material      TYPE zcm_petcrm,
ls_material_mem  TYPE zcm_petcrm.
DATA: lv_xml           TYPE string.
DATA: lv_clave         TYPE ihttpval.
DATA: lt_cabecera      TYPE tihttpnvp.
DATA: lt_material      TYPE TABLE OF zcm_petcrm.
DATA: lt_string        TYPE aco_tt_string.
DATA: xml_out          TYPE aco_string.
DATA: lv_resultado     TYPE string.
DATA: ls_marm          TYPE xdmarm.
DATA: lv_estado        TYPE char200.
DATA: lv_longitud      TYPE ihttpval.

*  break neo02.

SELECT SINGLE valores INTO lv_estado
FROM  zcm_parametros
WHERE kschl   EQ lc_estado
AND   valores EQ lc_activo.
IF sy-subrc EQ 0.
CHECK i_mara_new-matnr CP ‘SDL*’.

COMMIT WORK AND WAIT.» Espero que se actualicen las modificaciones

CREATE OBJECT carga_materiales TYPE zcarga_materiales_petcrm.
CREATE OBJECT conexion TYPE zconexion_crm_petcrm.

carga_materiales->datos_modificar( EXPORTING im_matnr = i_mara_new-matnr IMPORTING ex_material = ls_material ).
TRANSLATE ls_material-matnr TO UPPER CASE.

IF ls_material-kmein IS INITIAL.» Si el material es nuevo
LOOP AT t_marm_new INTO ls_marm.
IF sy-tabix EQ 1.
ls_material-kmein = ls_marm-meinh.
ELSEIF sy-tabix EQ 2.
ls_material-meinh = ls_marm-meinh.
ls_material-umren = ls_marm-umren.
ENDIF.» sy-tabix EQ 1.
ENDLOOP.»  AT t_marm_new INTO ls_marm.
ls_material_mem = ls_material.
EXPORT ls_material_mem FROM ls_material_mem TO SHARED MEMORY indx(al) ID ‘AJC’.
ELSE.
conexion->get_url( EXPORTING im_identificador = ls_material-matnr IMPORTING ex_url = lv_url ).
conexion->crear_cliente_http( EXPORTING im_url = lv_url IMPORTING ex_cliente_http = lv_cliente ).
conexion->set_version( EXPORTING im_version = lc_version_uno IMPORTING ex_cliente_http = lv_cliente ).
conexion->set_post( IMPORTING ex_cliente_http = lv_cliente ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_content_type im_valor = lc_content_valor IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->get_clave( EXPORTING im_nombre_so10 = lc_so10 IMPORTING ex_clave = lv_clave ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_autorizar im_valor = lv_clave IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->set_datos_cabecera( EXPORTING im_datos_cabecera = lt_cabecera IMPORTING ex_cliente_http = lv_cliente ).
conexion->convertir_formato_post( EXPORTING im_estructura = ls_material im_nombre_estructura = lc_nombre_estructura IMPORTING ex_conversion = lv_xml ).
carga_materiales->convertir_xml( EXPORTING im_conversion = lv_xml im_nombre_estructura = lc_nombre_estructura IMPORTING ex_conversion = lv_xml ).
conexion->get_longitud( EXPORTING im_xml = lv_xml IMPORTING ex_longitud = lv_longitud ).
conexion->rellenar_cabecera( EXPORTING im_nombre = lc_content_lenght im_valor = lv_longitud IMPORTING ex_datos_cabecera = lt_cabecera ).
conexion->set_datos_body( EXPORTING im_datos_body = lv_xml IMPORTING ex_cliente_http = lv_cliente ).
conexion->enviar_datos( EXPORTING im_cliente_http = lv_cliente im_dato = ls_material-matnr IMPORTING ex_resultado = lv_resultado ).
ENDIF.» ls_material-kmein IS INITIAL.
ENDIF.» sy-subrc EQ 0.
ENDFUNCTION.

Manual SAP Workflow

Es una herramienta que permite la implementación técnica de procesos de negocio complejos independientemente del tiempo y del lugar.

El flujo de trabajo es controlado y coordinado activamente por el sistema workflow. El control incluye la monitorización de pasos de trabajo individuales y el inicio de procesos para escalar las tareas que lleguen a su fecha de vencimiento.

El sistema workflow se integra completamente con las funciones de negocio del sistema R/3 a través de su Business Object Repository BOR en la transacción SWO1.

Adicionalmente el sistema Workflow permite su integración con la gestión de la organización, lo que permite relacionar personas o estructuras organizativas a las tareas del workflow.

a

Creación de un Workflow

A continuación se indican los pasos que se tienen que realizar para la creación de un workflow y comprede la siguiente arquitectura.

b

Definición e implementación del Business Object Repository

Lo primero que se tiene que hacer es la creación del BOR, que se realiza en la transacción SWO1.

c

  • Vamos a la transacción SWO1

d

Conforme lo creamos sale de la siguiente forma.

1

Estado de un tipo de objeto

A continuación se indican los estados de un tipo de objeto:

  • Modelado : En este estado el tipo de objeto no se puede instanciar, es decir no se pueden generar objetos de este tipo.
  • Implementado : Solo para pruebas, uso interno o posiblemente inestable.
  • Liberado : Liberado para ser utilizado por el cliente, solo se podrán realizar ampliaciones pero no modificar radicalmente el tipo.
  • Obsoleto : El tipo de objeto ha sido reemplazado por otro.

2

A continuación vamos a indicar que el BOR está como tipo de objeto “Implementado” y luego vamos a Grabar y generar y luego en “Liberado”.

3

Desarrollo de un tipo de objeto campo clave

A continuación lo que se tendrá que generar los campos claves del objeto que acabamos de crear.

4

5

6

A continuación grabaremos y generaremos el objeto, una vez grabado pondremos el campo clave primero en “Implementado” y luego en “Liberado”.

Desarrollo de un tipo de objeto atributo

A continuación lo que se tendrá que generar los atributos del objeto que acabamos de crear.

Los atributos pueden ser o de base de datos o virtuales, en este ejemplo crearemos un atributo virtual.

Atributo virtual

Al generar un atributo virtual el sistema no generará el código automáticamente pero si nos presentará donde debemos colocar el programa (entre las clausulas GET_PROPERTY y END_PROPERTY).

El atributo se crea mediante el programa (como una variable) y luego se coloca como resultado en el container del objeto mediante la macro SWC_SET_ELEMENT.

En el caso que el atributo virtual sea un objeto deberemos instanciar un objeto mediante la macro SWC_CREATE_OBJECT.

7

8

9

10

A continuación grabaremos y generaremos el objeto, una vez grabado pondremos el atributo primero en “Implementado” y luego en “Liberado”.

Ahora se tendrá que implementar el código del atributo.

11

get_property estado changing container.

SELECT SINGLE estado INTO object-estado
FROM zprocesowf
WHERE identificador EQ object-key-identificador.

swc_set_element container ‘estado’ object-estado.
end_property.

Desarrollo de un tipo de objeto método

Los métodos son las actividades que podemos llevar a cabo sobre un objeto, pueden ser de dos tipos:

  • Asincronos: El resultado siempre es enviado de vuelta al programa llamador en la forma de un evento
  • Sincronos: El resultado es enviado directamente al programa que lo ejecuto.

Ambos tipos de métodos pueden recibir datos a través de parámetros (parámetros de importanción) .

12

13

14

A continuación grabaremos y generaremos el objeto, una vez grabado pondremos el método, primero en “Implementado” y luego en “Liberado”.

Después se tendrá que realizar la implementación del método.

15

16

begin_method cambiarestado changing container.

DATA: lv_identificador TYPE numc10,
lv_estado         TYPE cms_re_dte_obj_cond.
DATA: ls_proceso       TYPE zprocesowf.

swc_get_element container ‘IDENTIFICADOR’ lv_identificador.» Dato de entrada de la tarea
swc_get_element container ‘ESTADO’ lv_estado.» Dato de entrada de la tarea

UPDATE zprocesowf
SET   estado        = lv_estado
WHERE identificador = lv_identificador.

COMMIT WORK AND WAIT.

swc_set_element container ‘ESTADO’ lv_estado.» Dato de salida de la tarea.

end_method.» Cambiar estado

Después de realizar la implementación se tendrán que declarar los parámetros.

17

18

19

20

Desarrollo de un tipo de objeto evento

Para lanzar el workflow se tendrá que definir un evento de lanzamiento.

21

22

23

A continuación grabaremos y generaremos el objeto, una vez grabado pondremos el evento primero en “Implementado” y luego en “Liberado”.

Definición e implementación del Workflow

Para realizar la implementación del workflow vamos a la transacción PFTC,

24

  • Datos del container

Lo primero que se tiene que hacer es incluir en el container el BOR que hemos creado.

25

  • Datos básicos

26

  • Workflow Builder

A continuación se definirá el proceso de negocio mediante el workflow builder y el evento desencadenante del workflow.

27

  • Definición del evento desencadenante

28

29

30

31

Crear Tarea

Primero se tiene que crear una tarea en la Transacción PFTC para luego asociarla a una actividad del workflow.

32

33

34

Ahora se tiene que crear la actividad

35

Ponemos la tarea antes creada

36

37

Tarea de decisión de usuario

A continuación vamos hacer una tarea de decisión de usuario, para enviar una tarea al Workitem de un un usuario.

38

39

Después vamos a la transacción SE37, para crear la función que determinará el responsable

40

ACTOR_TAB            LIKE    SWHACTOR

AC_CONTAINER      LIKE    SWCONT

FUNCTION zwf_usuario_tarea.
*»———————————————————————-
*»*»Interfase local
*»  TABLES
*»      ACTOR_TAB STRUCTURE  SWHACTOR
*»      AC_CONTAINER STRUCTURE  SWCONT
*»———————————————————————-

INCLUDE <cntain>.» Incluimos el container del BOR

DATA: lv_identificador TYPE numc10,
lv_estado        TYPE cms_re_dte_obj_cond.
DATA: ls_log           TYPE zlog_procesowf.

swc_get_element ac_container ‘IDENTIFICADOR’ lv_identificador.
swc_get_element ac_container ‘ESTADO’ lv_estado.

actor_tab-otype = ‘US’.
actor_tab-objid = sy-uname.
APPEND actor_tab.

actor_tab-otype = ‘US’.
actor_tab-objid = ‘AJIMENEZ’.
APPEND actor_tab.

ls_log-identificador = lv_identificador.
ls_log-estado        = lv_estado.
CONCATENATE ‘US’ ‘AJIMENEZ’ INTO ls_log-usuario.
ls_log-fecha         = sy-datum.
ls_log-hora          = sy-uzeit.

INSERT zlog_procesowf FROM ls_log.

COMMIT WORK AND WAIT.

ENDFUNCTION

Después vamos a la transacción PFAC.

41

42

43

Creamos la actividad en el workflow

44

Se pone el número de la regla que acabamos de crear.

45

46

A continuación se pone la tarea que hemos creado

47

48

Cuando se lanza el workflow tiene que salir lo siguiente.

49

50

A continuación muestro como se ve el Worflow.

51

Programa para lanzar Workflow

*&———————————————————————*
*& Report  ZLANZAR_WF
*&
*&———————————————————————*
*&
*&
*&———————————————————————*

REPORT zlanzar_wf.

TABLES: zprocesowf.

CONSTANTS: lc_estado TYPE cms_re_dte_obj_cond VALUE ‘INICIO’.

DATA: lv_rango         TYPE numc10,
ls_proceso       TYPE zprocesowf.
DATA: lv_identificador LIKE swr_struct-object_key,
lv_evento        LIKE swr_struct-event,
lv_swf_xmlcnt    TYPE swf_xmlcnt,
lv_swf_xmlsiz    TYPE swf_xmlsiz,
lt_mensaje       TYPE TABLE OF swr_messag.

CALL FUNCTION ‘NUMBER_GET_NEXT’ » número para el Log
EXPORTING
nr_range_nr = ’01’
object      = ‘ZPROCESO’
quantity    = ‘1’
IMPORTING
number      = lv_rango.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

ls_proceso-identificador = lv_rango.
ls_proceso-estado        = lc_estado.

INSERT zprocesowf FROM ls_proceso.

COMMIT WORK AND WAIT.

lv_identificador = ls_proceso-identificador.
lv_evento        = ls_proceso-estado.

CALL FUNCTION ‘SWF_CREATE_EVENT’
EXPORTING
object_type    = ‘ZPROCESOWF’
object_key     = lv_identificador
event          = lv_evento
xml_container  = lv_swf_xmlcnt
xml_size       = lv_swf_xmlsiz
commit_work    = ‘X’
event_language = sy-langu
language       = sy-langu
user           = sy-uname
TABLES
message_lines  = lt_mensaje.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.