lunes, 28 de octubre de 2013

Obtención de parámetros en una entidad.



Una de las dudas que me surgen siempre cuando estoy desarrollando es qué parámetros tengo en una entidad. 

El saber los parámetros me sirve para poder realizar controles en tiempo de ejecución, entre otras cosas.
Podemos averiguar los parámetros de una entidad por debuggin, navegando en el objeto ME hasta llegar a la estructura que contiene los datos

En concreto la navegación por el objeto es la siguiente:

ME->TYPED_CONTEXT->objeto a tratar-> ATTR_STRUCT_NAME

Una forma más sencilla es obtener desde el código un field symbol con los parámetros de la entidad, de la siguiente forma:

lr_entity ?= me->typed_context->btadminh->collection_wrapper->get_current( ).

DATA: lv_att_struc_name TYPE strukname,
ref_rowtype TYPE REF TO cl_abap_structdescr,
ref_wa TYPE REF TO data.
FIELD-SYMBOLS: <fs_properties> TYPE ANY.

lv_att_struc_name = lr_entity2->get_attr_struct_name( ).
ref_rowtype ?= cl_abap_typedescr=>describe_by_name( lv_att_struc_name ).
CREATE DATA ref_wa TYPE HANDLE ref_rowtype.
ASSIGN ref_wa->* TO <fs_properties>.


lr_entity->if_bol_bo_property_access~get_properties( IMPORTING es_attributes = <fs_properties> ).

En el field symbols tenemos todas las propiedades y accedemos a ellas tan simple como field-dato

miércoles, 9 de octubre de 2013

Establecer filtro por defecto en búsquedas


Es muy habitual que en cualquier búsqueda se nos solicite que uno de los filtros tenga un valor por defecto y que además este filtro sea modificable por el usuario. Vamos a ver como hacerlo.

Vamos a tratar el ejemplo concreto de la búsqueda de clientes. El filtro que nos solicitan es que la marca de borrado esté como "No marcado".
Las modificaciones las debemos hacer en la carga de la pantalla así que trataremos el método DO_INIT_CONTEXT. Obviamente si el componenete no está ampliado tendremos que ampliarlo, podéis ver en este post como hacerlo. El componente a tratar en este caso es BP_HEAD_SEARCH.
Para modificar el valor estándar debemos obtener la query con la que estamos trabajando:


lv_cnode get_dquery_cnode( ).
lr_qs ?= lv_cnode
->collection_wrapper->get_first( ).

Si la query no existiese obtenemos la instancia de query con la que está trabajando el sistema:

IF lr_qs IS NOT BOUND.
    lr_qs 
cl_crm_bol_dquery_service=>get_instance'BuilHeaderAdvancedSearch).
    lv_cnode
->collection_wrapper->addlr_qs ).
ENDIF.

 A continuación obtenemos los parámetros de la query y los recorremos para buscar el que nos interesa. En este caso el parámetro que nos interesa es XDELE. A continuación borramos el parámetro y lo volvemos a crear con el valor que nos interesa. Aunque no es la forma más elegante de hacerlo es efectiva:

lv_params ?= lr_qs->get_selection_params( ).
  lv_property ?= lv_params
->get_first( ).
  
IF lv_property IS BOUND.
    
WHILE lv_property IS BOUND.

      lv_name ?= lv_property->get_property'ATTR_NAME).
      
IF lv_name->'XDELE'.
        lv_params
->removelv_property ).
        new_selection_parameter 
=
                  lr_qs
->insert_selection_paramiv_attr_name 'XDELE'
                  iv_sign 
'I'
                  iv_option 
'EQ'
                  iv_low 
'N'
                  iv_index 
).

        
EXIT.
      
ELSE.
        lv_property ?= lv_params
->get_next( ).
      
ENDIF.
    
ENDWHILE.
ENDIF.

Obviamente como siempre llamámos al método superior. En este caso nos interesa llamarlo al final de la ejecución del método.


CALL METHOD super->do_init_context.

Por último, el detalle desquiciante, es que esto no funciona si no redefinimos el método DO_PREPARE_OUTPUT. En este método es necesario llamar al método superior pero sin indicar el parámetro iv_fiirst_time. De esta forma funcionará bien en todas las ejecuciones.

Y con esto conseguimos un filtro por defecto en las búsquedas, pero que puede ser eliminado en caso necesario.

Os incluyo la definición de variables para que todo sea más sencillo


    DATA lv_cnode TYPE REF TO cl_bsp_wd_context_node_asp.
  
DATA lr_qs TYPE REF TO cl_crm_bol_dquery_service.
  
DATA new_selection_parameter TYPE REF TO if_bol_selection_param.
  
DATA lv_params TYPE REF TO if_bol_bo_col.
  
DATA lv_property TYPE REF TO if_bol_bo_property_access.
  
DATA lv_name TYPE REF TO name_komp.
  
DATAlv_profile TYPE REF TO if_crm_ui_profile,
       lv_profile_name 
TYPE bsp_dlc_object_type.



lunes, 22 de julio de 2013

Asignaciones en el modelo de organización


Supongo que todos los que trabajáis parametrizando CRM conocéis el modelo de organización.
Desde el modelo de organización montamos la estructura de nuestra compañía para después utilizarla para dar permisos, asignar oficinas de ventas, y montar la estructura organizativa en general.
Me han llegado a decir que la estructura es la base de CRM y que la definición de las "cajitas" es lo más importante en la implementación de CRM. En mi humilde opinión la definición de la estructura es un paso importante, pero no es el que decidirá el éxito o el fracaso de la implementación ya que el sistema tiene muchos más puntos a tratar y este en concreto es fácilmente modificable.

No voy a entrar en más detalles de la estructura ya que creo que la problemática que presenta es más de definición que de implementación pero me he encontrado con muchos problemas y muy difíciles de diagnosticar por malas prácticas en la gestión de esta estructura y ese es el punto que quiero tratar hoy.

En concreto he encontrado problemas con la copia de nodos dentro de la estructura. Es una situación bastante común en una empresa en expansión que tengamos que crear nuevos nodos para reflejar la realidad de la compañía. Este nodo puede ser un nuevo centro, una nueva sociedad o simplemente un nuevo supervisor o comercial de zona.

Para esto, y como las estructuras suelen ser análogas es una práctica común el copiar un nido similar y cambiarle el nombre y un par de características para crear el nuevo. Esto no es un mal hábito en sí, pero se debe tener en cuenta que al copiar un nodo no solo se copia el nodo, si no que estamos copiando todas las asignaciones.
Así si copiamos el nodo que corresponde al "jefe del área 1" para crear al "jefe del área 2" este segundo tendrá la asignación como jefe tanto de su área como del área de la que está copiado.

Para tratar estos casos debemos modificar estas asignaciones. Para ello el primer paso es entrar en el modelo de organización mediante la transacción PPOMA_CRM. A continuación hacemos doble click en el nodo a tratar y vamos al menú "Pasar a-> Obj. detallado-> Descripción de objetos ampliada":





Marcamos la entrada de enlaces:

Y presionamos el botón .
Esto nos da todas las asignaciones del objeto:


Con estas asignaciones es con las que tenemos que trabajar, borrar, modificar... En este punto podemos incluso definir periodos de validez y jugar con las asignaciones según los intereses de nuestra empresa.

Espero os sea de utilidad.