lunes, 4 de junio de 2012

Programación BOL/GenIL Crear nuevo bloque (4/7)

Seguimos con la programación BOL/GenIL y ahora vamos a ver que necesitamos para que la clase que hemos creado pueda crear, borrar y modificar entradas

  • Creación de entradas
    Voy a intentar que la creación de entradas sea de la forma más sencilla posible, con los campos clave crearemos la entrada en la tabla y luego volvemos a recuperar la tabla en los objetos. Debemos ampliar el método IF_GENIL_APPL_INTLAY~CREATE OBJECTS
    DATAls_parameters TYPE crmt_name_value_pair,
         ls_estructura
    TYPE ztabla_bol,
         lt_request_obj 
    TYPE crmt_request_obj_tab..

    * Creo una entrada en la tabla con los datos que van en la tabla de parámetros
      
    READ TABLE it_parameters INTO ls_parameters WITH KEY name = 'ACT_GUID'.
      
    IF sy-subrc 0.
        ls_estructura
    -act_guid ls_parameters-value.
      
    ENDIF.
      
    READ TABLE it_parameters INTO ls_parameters WITH KEY name = 'ID'.
      
    IF sy-subrc 0.
        ls_estrucutra
    -id ls_parameters-value.
      
    ENDIF.

    * Inserto la entrada en la tabla
      
    INSERT ztabla_bol FROM ls_estrucutra.

      
    me->if_genil_appl_intlay~get_objectsit_request_objects lt_request_obj
                                           iv_root_list       
    iv_root_list ).
  • Modificación de datos
    Para modificar los datos primero es necesario bloquearlos, para eso ampliaremos el método IF_GENIL_ALTERNATIVE_DSIL~LOCK_OBJECTS y luego modificarlos ampliando el método IF_GENIL_APPL_INTLAY~MODIFY_OBJECTS
    • Método IF_GENIL_ALTERNATIVE_DSIL~LOCK_OBJECTS
      El objetivo de este método es bloquear el objeto para que no pueda ser modificado en el mismo momento por otra sesión. Realmente del bloqueo se encarga el objeto al que está asociado nuestro bloque, en este caso una tarea. Por lo tanto lo único que necesitamos es que el método informe de que todo es OK.
      FIELD-SYMBOLS <ls_object> LIKE LINE OF ct_object_list.

        
      LOOP AT ct_object_list ASSIGNING <ls_object>.
          <ls_object>
      -success abap_true.
        
      ENDLOOP.
    •  Método IF_GENIL_APPL_INTLAY~MODIFY_OBJECTS
      Este método obtiene los campos modificados y modifica la BD. Si tenemos datos obligatorios en este método también podemos controlarlos para no modificar la BD si no se están informando.
      DATAlv_objeto TYPE REF TO if_genil_cont_root_object,
           lv_id 
      TYPE ztabla_bol-id,
           lv_props_obj 
      TYPE REF TO if_genil_obj_attr_properties,
           lt_changed_attr 
      TYPE crmt_attr_name_tab,
           ls_attributes   
      TYPE zestructura_bol,
           ls_objeto
      TYPE ztabla_bol.

        
      FIELD-SYMBOLS<new> TYPE simple,
                     <old> 
      TYPE simple,
                     <name> 
      TYPE name_komp.

        lv_expo 
      iv_root_list->get_first( ).

        
      WHILE lv_objeto IS BOUND.

      *   Comprobamos si han habido modificaciones
          
      IF lv_expo->get_delta_flag( ) = if_genil_cont_simple_object=>delta_changed.
      *     Obtenemos las propiedades de los atributos
            lv_props_obj 
      lv_expo->get_attr_props_obj( ).
      *     Comprobamos cuales se han modificado
            
      CALL METHOD lv_props_obj->get_name_tab_4_property
              
      EXPORTING
                iv_property 
      if_genil_obj_attr_properties=>modified
              
      IMPORTING
                et_names    
      lt_changed_attr.

      *     ID
            
      CALL METHOD lv_objeto->get_key
              
      IMPORTING
                es_key 
      lv_id.

      *     Atributos de la estrucutra
            
      CALL METHOD lv_objeto->get_attributes
              
      IMPORTING
                es_attributes 
      ls_attributes.

      *     Obtengo la entrada en la tabla
            
      SELECT SINGLE INTO ls_objeto
              
      FROM ztabla_bol
              
      WHERE id lv_id.

            
      LOOP AT lt_changed_attr ASSIGNING <name>.
              
      ASSIGN COMPONENT  <name> OF STRUCTURE ls_objeto TO <old>.
              
      ASSIGN COMPONENT <name> OF STRUCTURE ls_attributes TO <new>.
              <old> 
      <new>.
            
      ENDLOOP.

            
      UPDATE ztabla_bol FROM ls_objeto.

          
      ENDIF.

          lv_objeto
      iv_root_list->get_next( ).
        
      ENDWHILE.
    • Borrado de entradas
      Para borrar simplemente obtendremos el ID y borramos sin más. Hay que ampliar el método IF_GENIL_APPL_ALTERNATIVE_DSIL~DELETE_OBJECTS
      DATAlv_id TYPE ztabla_bol-id.
        
      FIELD-SYMBOLS<obj> TYPE crmt_genil_obj_inst_line.

        
      LOOP AT ct_object_list ASSIGNING <obj>.
      * Obtengo el ID de la tabla
          
      CALL METHOD cl_crm_genil_container_tools=>get_key_from_object_id
            
      EXPORTING
              iv_object_name 
      <obj>-object_name
              iv_object_id   
      <obj>-object_id
            
      IMPORTING
              es_key         
      lv_id.

      * Borro la entrada en la tabla
          
      DELETE FROM ztabla_bol WHERE id lv_id.

        
      ENDLOOP.
Con esto finalizamos las modificaciones en la clase de control de nuestro nuevo bloque

Relacionado:
Programación BOL/GenIL (1/.)
Programación BOL/GenIL (2/.)
Programación BOL/GenIL (3/.)
Programación BOL/GenIL (5/.)  
Programación BOL/GenIL.(7/7)

viernes, 4 de mayo de 2012

Programación BOL/GenIL. Crear nuevo bloque (3/7)

Siguiendo los post de programación GenIL vamos un paso más allá modificando nuestra clase para darle la funcionalidad que necesitamos.

La clase que hemos creado debe heredar obligatoriamente de la clase CL_CRM_GENIL_ABSTR_COMPONENT2. Con esto nos aseguramos que tenemos todos los métodos necesarios para su buen funcionamiento. Si no hiciesemos esto las llamadas desde el WebUI nos provocarían dumps continuamente.

Vamos a ver paso a paso que tenemos que ampliar en esta clase, en este primer post como obtener datos

  • Obtención de objetos y modelos
    Lo primero que necesitamos es obtener los objetos y modelos que hemos definido en las diferentes tablas. Los métodos a redefinir los siguientes
     
    • Método IF_GENIL_APPL_MODEL~GET_MODEL
      Debemos obtener los modelos de la tabla correspondiente. Insertar el siguiente código:

      SELECT * FROM ztabla_modelo
      INTO CORRESPONDING FIELDS OF TABLE rt_relation_det.  

       
    • Método IF_GENIL_APPL_MODEL~GET_OBJECT_PROPS
      Debemos obtener los modelos de la tabla correspondiente. Insertar el siguiente código:

      SELECT * FROM ztabla_objetos
      INTO CORRESPONDIG FIELDS OF TABLE rt_obj_props.

       
    • Método IF_GENIL_APPL_INTLAY~GET_OBJECTS.
      Este método transforma la entrada interna del objeto en un objeto de la BD. Insertar el siguiente código.

      DATA: lr_object TYPE  REF TO if_genil_container_object,
            lr_msg_cont TYPE REF TO cl_crm_genil_global_mess_cont,
            lv_name_obj TYPE ztabla-id,
            lr_attr_props TYPE REF TO if_genil_obj_attr_properties,
            l_result TYPE ztabla,
            lv_name TYPE crmt_ext_obj_name.
      * Cogemos la primera entrada de la tabla
      lr_object = iv_root_list->get_first( ).
      lr_msg_cont ?= iv_root_list->get_global_message_container().
      WHILE lr_object IS BOUND.
        lv_name = lr_object->get_name( ).
        IF lr_object->check_attr_requested( ) = abap_false.
          CALL METHOD lr_object->get_key
            IMPORTING
      es_key = lv_name_obj.

          SELECT SINGLE * FROM  ztabla
            INTO CORRESPONDING FIELDS OF l_result
            WHERE id = lv_name_obj.

          lr_object->set_attributes( l_result ).
          lr_attr_props = lr_object->get_attr_props_obj( ).
          lr_attr_props->set_all_properties( if_genil_obj_attr_properties=>changeable ).
        ENDIF.
        lr_object = iv_root_list->get_next( ).
      ENDWHILE.
  •  Selección de datos
    Para la selección de datos es necesario definir en primer lugar un tipo local mediante el botón para poder realizar búsquedas por rangos. El tipo se define de la siguiente manera:
    TYPES: BEGIN OF ty_general_rng,
      sign TYPE bapisign,
      option TYPE bapioption,
      low TYPE string,
      high TYPE string,
    END OF ty_general_rng.
    TYPES: tt_general_rng TYPE STANDARD TABLE OF ty_general_rng.

    A continuación redefinimos el siguiente método:
    • Método IF_GENIL_APPL_INTLAY~GET_DYNAMIC_QUERY_RESULT
      Para hacer la selección se realizará un select con todos los parámetros de la tabla asignando los parámetros a rangos. En el ejemplo solo filtro por un campo pero su puede utilizar cualquiera de la tabla. Hay que implementar el siguiente código.

      DATA:lr_object TYPE REF TO if_genil_cont_root_object,
           lt_result TYPE TABLE OF zestructura,
           lv_dyn_where TYPE string,
           lv_len TYPE i,
           ls_range TYPE tt_general_rng.
      * Variables para la búsqueda
      DATA: lt_variable TYPE tt_general_rng.
      FIELD-SYMBOLS: <fs_result> TYPE zestructura,
                     <fs_selection_range> TYPE genilt_selection_parameter.
      *Se recorren los parámetros
      LOOP AT it_selection_parameters[] ASSIGNING <fs_selection_range>
        MOVE: <fs_selection_range>-sign TO ls_range-sign,
              <fs_selection_range>-option TO ls_range-option,
              <fs_selection_range>-low TO ls_range-low,
              <fs_selection_range>-high TO ls_range-high.
        CASE <fs_selection_range>-attr_name.
          WHEN 'NOMBRE_CAMPO'.
            APPEND ls_range TO lt_variable[].
        ENDCASE.
        CLEAR ls_range.
      ENDLOOP.
      *Obtengo los datos de la tabla.
      SELECT * FROM ztabla INTO TABLE lt_result
        WHERE id IN lt_id
          AND campò IN lt_variable.

      CHECK LINES ( lt_result[] ) > 0.
      * Asigno el resultado
      LOOP AT lt_result ASSIGNING <fs_result>. 
        lr_object = iv_root_list->add_object( iv_object_name = 'Root'

        is_object_key = <fs_result>-id ).
        CHECK lr_object IS BOUND.
        lr_object->set_query_root( abap_true ).
      ENDLOOP.

En el siguiente post veremos como crear, modificar y borrar entradas.

Relacionado:
Programación Bol/GenIL (1/.)
Programación Bol/GenIL (2/.)
Programación Bol/GenIL (4/.)
Programación Bol/GenIL (5/.)   
Programación BOL/GenIL (6/.)

martes, 27 de marzo de 2012

Programación BOL/GenIL. Crear nuevo bloque (2/7)

Siguiendo el primer post de programación BOL que podeis ver aquí a continuación vamos a ver el customizing necesario para que el bloque sea visible en nuestra actividad.

Lo primero que necesitamos es relacionar el componente con nuestra tabla Z. Básicamente es indicarle al componente que también debe tener en cuenta nuestra tabla y además definir una clase para gestionarla.

  • Definición del componente
    La ruta para definir el componente es SPRO-> Customer Relationship Management-> CRM Componentes multiaplicacionales-> Layer de interacción/Objeto genérico-> Parametrizaciones básicas
    Seleccionamos definición del componente y creamos un nuevo componente con su descripción e indicamos la tabla de objetos y de modelos que hemos definido anteriormente. En este punto hay que definir la clase que va a implementar el componente. Os recomiendo comenzar el nombre de la clase por ZL para mantener una nomenclatura lo más estándar posible. La definición de esta clase la veremos más adelante. En este mismo punto podemos ver las definiciones estándar. Estas definiciones nos sirven como modelo para definir la tabla de objetos y la tabla de modelos tanto en estructura como en datos. El componente que he usado como modelo es el MP. También se puede utilizar la clase de estos modelos estándar para ayudarnos a definir la nuestra.

  • Set de componentes
    A continuación debemos asignar nuestro componente al set que nos interese. Es necesario averiguar el set que se corresponde con el componente que vamos a ampliar. Para ello obtenemos el componente que queremos ampliar en WebUI, y vamos a la ampliación del componente (tx BSP_WD_CMPWB) . En este caso concreto el componente es el BT125H_TASK. Visualizamos el componente y vamos a la opción "Editor de repository en tiempo de validez" y expandimos la carpeta "Models"

    El set de componentes es el que indica el modelo, en este caso ONEORDER. Volvemos al punto de customizing anterior y en este caso seleccionamos "Definición de set de componentes". Aqui buscamos nuestro set. Lo marcamos y seleccionamos "Asignación de componentes". Ahora añadimos una nueva entrada con el componente Z que hemos creado en el punto anterior.
Con esto hemos finalizado la parametrización necesaria para que funcione nuestra ampliación. Pero no hemos terminado, aún nos queda tarea por hacer, la veremos en siguientes post.

Relacionado:
Programación Bol/GenIL (1/.)
Programación Bol/GenIL (3/.)
Programación Bol/GenIL (4/.)
Programación Bol/GenIL (5/.)   
Programación Bol/GenIL (6/.)

miércoles, 14 de marzo de 2012

Programación BOL/GenIL. Crear nuevo bloque (1/7)

En los siguientes post voy a contaros como poner un nuevo bloque en una actividad que muestre los datos de una tabla Z. Obviamente esta tabla está relacionada con la actividad. Este tipo de bloque se conoce como programación BOL/GenIL y se puede extrapolar a cualquier tipo de pantalla/objeto en CRM.

En este primer post veremos como crear la estructura de datos necesaria para que los datos de una tabla Z nos sean útiles.

La entidad Bol necesita tres tablas y una estructura para que todo funcione. Se necesita una tabla para guardar los datos, una tabla para los objetos y otra para los modelos. También necesitamos una estructura idéntica a la tabla para la configuración. Ahora las vemos en detalle

  • Tabla  de datos
    La tabla de datos tiene el requisito de que la clave primaria debe componerse únicamente del mandante y del ID. El ID puede ser de cualquier tipo , GUID de CRM, numérico, alfanumérico, no hay restricción, pero sólo un campo de ID. También necesitamos un campo de relación con el objeto en el que vamos a colgar la tabla. Lo normal es que este campo sea un GUID de CRM. Se puede utilizar el ID de visualización pero internamente se trabaja mejor con el GUID. En la tabla si definimos los campos con un elemento de datos del sistema o propio tendremos las descripciones directamente en web con lo que nos ahorramos el tener que definirlas en ese entorno. Por lo demás la tabla la definís con los campos que queráis sin restricciones.

  • Estructura
    La estructura debe ser idéntica a la tabla. Por lo demás no hay ningún tipo de restricción para la estructura

  • Tabla de objetos
    Esta tabla indica los objetos que posee nuestra entidad BOL. El objeto básico que necesitamos es el objeto Raiz pero se puede definir cualquier otro tipo de objeto como objeto de búsqueda, objeto resultado, objeto de texto... La tabla de referencia que he utilizado en este ejemplo es la CRMC_OBJS_MPIL. En los siguientes post os indicaré como obtener la tabla de modelo, por ahora con que sepáis que se copia de esta es suficiente. La estructura de la tabla es la siguiente:

    El dato básico a rellenar es:
    Object_name -> Root
    Object_kind -> A
    Key_struct -> "Nombre de la estructura"
    Attr_struct -> "Nombre de la estructura"

  • Tabla de modelo
    La tabla de modelo define las relaciones entre los diferentes componentes. Es necesario definir el modelo para el objeto Root que se relaciona con él mismo. La tabla de modelo que he utilizado es la CRMC_MODEL_MPIL. Como en el caso anterior os explicaré de donde obtener el modelo y por que ese modelo en los siguientes post. La estructura de la tabla es la siguiente:

    Y la entrada que se deben crear, como mínimo es:

    Es necesario relacionar mediante una clave externa esta tabla de modelo y la tabla de objetos. La clave la creamos mediante el icono de la llave y se crea sobre el campo "OBJECT_A" con los siguientes datos:

Con esto  tenemos toda la estructura de datos creada y preparada para el customizing.