Procesos con Items de Opción multiple - Apex

No solo con listas de opción múltiple, si no también con checkbox y shuttles. De esto no tengo referencias por que esto lo hizo un compañero hace rato y de ahí en adelante fue puro copy-paste :P

Para esto usaremos una base de datos basada en 3 tablas, FANCLUB, FAN y la relación intermedia FAN_FANCLUB. La relación entre un Fan y un Fanclub es n-n (por que uno tiene derecho a que le guste más de un artista :P), por eso se crea la tabla intermedia FAN_FANCLUB. El ejemplo con el que mostrare esto se centrara en la página de edición de Fan, en donde podremos seleccionar a que fan clubs pertenece, eso lo haremos a través de un shuttle.

Al momento de aplicar cambios debemos verificar que los fanclubs al lado izquierdo del shuttle no existan ya en la Base de datos, si es así las agregamos y le asignamos un código dependiendo del ultimo código asignado en ese fanclub, es por eso que no podemos eliminarlos y volverlos a crear. También debemos eliminar las que están en la Base de datos y no fueron seleccionadas, es decir, ya no son fan de ese artista u_u. Ahora que sabemos lo que tendrá que hacer la página, es momento de hacerla. Pueden descargar la app aquí junto con los script de Base de Datos.

Los items de selección múltiple devuelven las opciones seleccionadas separadas por dos puntos, así 『opcion1:opcion2:opcion3 』, entonces para operarlos debemos convertirlos en un array con la ayuda de un elemento y una función de apex. esos elementos son
DECLARE
ID_FANCLUB_COLUMN APEX_APPLICATION_GLOBAL.VC_ARR2; 
ID_FANCLUB_STRING varchar2(4000);  
items APEX_APPLICATION_GLOBAL.VC_ARR2; 
ID_FANCLUB_COLUMN: Almacenara en un Array los id de los fanclub a los que pertenece el fan
ID_FANCLUB_STRING: Almcenara los id de los fanclub a los que pertenece el fan en el formato 1:2:3:4
items: Almacenara en un array las opciones que fueron seleccionadas en el shuttle

Lo primero que haremos sera eliminar los FanClub que no fueron seleccionados, para esto primero consultamos cuales están actualmente y los colocamos en la variable ID_FANCLUB_COLUMN, Luego tomamos uno a uno los id y miramos si están entre los elementos seleccionados con la función instr, tanto el id actual como el valor que retorna el item, los colocamos entre dos puntos, para que queden de una forma similar a esta:
Item= :1:2:3:4:
ID= :1:
De este modo sin importar si el id esta en uno de los extremos o en el centro, lo podremos encontrar con la función instr.
En caso de que no este entre los elementos seleccionados, lo eliminanos. El código pa' hacer todo lo que les explique es el siguiente:
BEGIN
-- Obtener en un array los fanclub asociados.
select  ID_FANCLUB
bulk collect into ID_FANCLUB_COLUMN 
from  FAN_FANCLUB
where  ID_FAN = :P10_ID_FAN;

-- Comparar los datos de la DB con los de la lista, si no esta se elimina
for i in 1..ID_FANCLUB_COLUMN.count loop
 -- Si el elemento de la BD no esta seleccionado
 IF(instr(':'||:P10_FANCLUB||':',':'||ID_FANCLUB_COLUMN(i)||':') = 0)then 
  delete  FAN_FANCLUB
  where ID_FANCLUB = ID_FANCLUB_COLUMN(i) AND ID_FAN = :P10_ID_FAN;
 END IF;
END LOOP;
Si ya sé, también lo pude haber hecho así y habría sido más eficiente, pero a veces si necesitamos comparar id por id para realizar otras operaciones, por eso lo hice de la forma larga, pero si no necesitan eso, les sirve con esto:
delete  FAN_FANCLUB
where instr(':'||:P10_FANCLUB||':',':'||ID_FANCLUB||':') = 0 
  AND ID_FAN = :P10_ID_FAN;

Ahora vamos con la segunda parte, ingresar los Fanclub nuevos, para esto recorreremos uno a uno los id seleccionados y si no están, se crean, para facilitar el recorrido de los datos seleccionados, convertimos lo que nos retorna el item en un array. También usaremos los datos de ID_FANCLUB_COLUMN para no realizar una consulta por cada ID, pero como esta variable es un Array, lo debemos convertir a un string con el formato :1:2:3: y compararlo con instr como hicimos para eliminar. EL código es el siguiente.
-- Convertir los valores del item en un array
items := APEX_UTIL.STRING_TO_TABLE(:P10_FANCLUB); 
-- convertir los valores asociados a un formato :ID1:ID2:ID3:
ID_FANCLUB_STRING := ':'||APEX_UTIL.TABLE_TO_STRING(ID_FANCLUB_COLUMN)||':'; 

-- Compararlos. Si no esta en la BD, crear el registro.
for i in 1..items.count loop 
 IF(instr(ID_FANCLUB_STRING,':'||items(i)||':') =0 )then 
  INSERT INTO FAN_FANCLUB values(NULL, items(i), :P10_ID_FAN, (SELECT nvl(max(CODE),0)+1 FROM FAN_FANCLUB WHERE ID_FANCLUB= items(i)) );
 END IF;
end loop;
Y listo, ya queda el código :) Y a celebrar jejeje...

Acá está todo el código en un solo bloque.
DECLARE
ID_FANCLUB_COLUMN APEX_APPLICATION_GLOBAL.VC_ARR2; 
ID_FANCLUB_STRING varchar2(4000);  
items APEX_APPLICATION_GLOBAL.VC_ARR2; 
BEGIN
-- Obtener en un array los deudores asociados.
select  ID_FANCLUB
bulk collect into ID_FANCLUB_COLUMN 
from  FAN_FANCLUB
where  ID_FAN = :P10_ID_FAN;

-- Comparar los datos de la DB con los de la lista, si no esta se elimina
for i in 1..ID_FANCLUB_COLUMN.count loop
 -- Si el elemento de la BD no esta seleccionado
 IF(instr(':'||:P10_FANCLUB||':',':'||ID_FANCLUB_COLUMN(i)||':') = 0)then 
  delete  FAN_FANCLUB
  where ID_FANCLUB = ID_FANCLUB_COLUMN(i) AND ID_FAN = :P10_ID_FAN;
 END IF;
END LOOP;


-- Convertir los valores del item en un array
items := APEX_UTIL.STRING_TO_TABLE(:P10_FANCLUB); 
-- convertir los valores asociados a un formato :ID1:ID2:ID3:
ID_FANCLUB_STRING := ':'||APEX_UTIL.TABLE_TO_STRING(ID_FANCLUB_COLUMN)||':'; 

-- Compararlos. Si no esta en la BD, crear el registro.
for i in 1..items.count loop 
 IF(instr(ID_FANCLUB_STRING,':'||items(i)||':') =0 )then 
  INSERT INTO FAN_FANCLUB values(NULL, items(i), :P10_ID_FAN, (SELECT nvl(max(CODE),0)+1 FROM FAN_FANCLUB WHERE ID_FANCLUB= items(i)) );
 END IF;
end loop;    

end;

El vídeo de esta vez es una pequeña muestra de lo que sera el próximo single de Perfume :) es muy corto, pero cuando salga el completo lo remplazare, jeje

Comments

Popular posts from this blog

View PDF File on APEX (Simple approach)

Set Custom APP Icon on APEX

ID Basado en trigger y secuencia para todas las tablas - Oracle