Orden de Compra - 2 niveles de autorización
Proceso BPM de tipo Transacción ERP que permite realizar un control sobre el importe de la Orden de Compra generada por el usuario, basándose en 2 niveles de autorización
Diagrama
Modo de Uso
Se crea una Orden de Compra con Seguimiento por un total de $12.100,00 del producto Kayak para el proveedor Aquatic S.R.L.
Luego de guardar el documento, para poder ver el caso que se ha generado:
Al cerrar y volver a abrir el pedido, se puede observar un nuevo botón “Ir a caso” en la Toolbar.
Se puede acceder desde Menú → WS → Procesos → Gestión de casos.
Se puede observar que la próxima actividad a ejecutar es Autorizar OC Nivel 1. Esto es porque de manera automática se corrió la actividad Notificar al gerente de Compras.
La persona responsable de llevar a cabo la autorización ha sido notificada mediante un mail que tiene esa tarea pendiente.
Al accionar la actividad, se deberá elegir la Evaluación entre “Aprobar”, “Rechazar” o “Modificar”.
Si en la evaluación se decide rechazar la orden de compra, el proceso seguirá con la actividad Notificar Solicitante. Esta actividad es de modo manual, por lo cual se deberá notificar a quien corresponda y luego ejecutar la tarea.
Si se desea modificar la Orden de Compra, se elige la opción modificar. El proceso mostrará Modificar OC como la próxima actividad pendiente. Esta es la única manera que se logra que la Orden de Compra se desfirme y se puedan realizar cambios. Una vez hecho los cambios se ejecuta la tarea de manera manual y vuelve a la actividad Autorizar OC nivel 1.
Si la evaluación es correcta y se aprueba, lo primero que realizará el proceso es fijarse si la Orden de Compra fue hecha por un monto menor o mayor al de $20.000.
Si el monto es menor, como es el caso de este ejemplo, la próxima actividad pendiente será Enviar OC al Proveedor.
Si es mayor, pasará por Autorizar OC Nivel 2, se harán los mismos pasos que la primera autorización, y si se aprueba, también se dirigirá a Enviar OC al Proveedor:
Esta tarea se realiza de manera manual. Se debe enviar la Orden de Compra a quién corresponda para luego ejecutarla. Una vez hecho esto, la próxima tarea de que es de tipo “Gestión Externa” será Recepcionar OC.
Esta última actividad del proceso es de tipo Gestión Externa, lo cual, se debe generar una Recepción de Compra con Seguimiento desde:
Menú → Operación → Compras → Recepciones.
Se genera una nueva Recepción de Compra con Seguimiento con asistente donde se debe elegir la Orden de Compra asociada al caso:
Luego de guardar la Recepción de Compra con Seguimiento, se reingresa al caso y se refresca. Se observa en el apartado gestión que se encuentra finalizado:
Si la recepción se realiza por el total de la orden de compra, como es este caso, el proceso se finalizará. En cambio si está incompleta, quedará pendiente la actividad Recepcionar OC hasta que se vincule totalmente.
Configuración del proceso
Se accede desde Menú→App Builder→ Diccionarios → Procesos, se selecciona “Autorización de Orden de Compra”.
El documento Orden de Compra con Seguimiento debe tener configurado en el apartado Seguimiento el modo “por Proceso” y seleccionar el proceso con el cual se está trabajando.
Se accede desde Menú → App Builder → Documentos → Tipos de Documento.
El proceso comienza con la actividad Inicio, presionamos el botón diagramar ubicado en la Toolbar:
La próxima actividad es Notificar al Gerente de Compras. El script de dicha actividad es el siguiente:
import app.bsuite.transacciones.operacion.OperacionHLP;
import app.bsuite.transacciones.operacion.model.OperacionVO;
import app.bsuite.transacciones.operacion.model.OperacionDF2VO;
String sessionID = params.getSessionID();
DBHelper dbh = params.getDBHelper();
CasoBPMAccionVO accion = params.get(“Accion”);
CasoScriptResultado result = new CasoScriptResultado();
UtilsHLP utils = new UtilsHLP(sessionID);
XMLManagerHLP xmlMgr = new XMLManagerHLP(sessionID);
MailSenderHLP sender = new MailSenderHLP(sessionID, dbh);
NotifierHLP notifier = new NotifierHLP(sessionID, dbh);
OperacionVO op = OperacionHLP.getByPrimaryKey(new OperacionVO(sessionID), accion.getTransaccionID(), dbh, false);
String numeroDocumento = op.getNumeroDocumento();
String nombre = op.getNombre();
//Date fecha = op.getFecha();
//String nombre1 = nombre.split(“-”)[0];
String asunto1 = "Comprobante : " + numeroDocumento; //agregar ;
//String dataXMLEntrada = caso.getDataXML();
String dataXMLSalida = “”;
String cuerpoMail = “”;
String link = “http://www.ceresteamplace.com/BSA/general/includes/appItem.jsp?fafViewCode=DF_VIEWER” +
“&pk=” + FafLong.val(accion.getTransaccionID()) +
“&claseVO=” + “CasoDirectoVO” +
“&FAFCLASE_FACADE=” + “FAFTransaccionBSuiteEJB” +
“&appitemID=50459”;
cuerpoMail += "Tiene pendiente de firma la Orden de Compra " +
“<a href="” + link + “">” + accion.getTitulo() + “”;
Destinatario destinatario = sender.getDestinatarioPersona(accion.getActividad().getPersonaIDResponsable());
asunto1= "Autorización de Orden de Compra (transaccionID " + accion.getTransaccionID().toString() + “)” + asunto1;
// El objeto mail está formado 3 parámetros: destinatario, Asunto del mail, Cuerpo del mail
// En la línea siguiente se ingresa el mail del usuario al que hay que informar que se rechazó el pedido
FAFMailCentral mail = sender.getSystemMail(“xxx@finnegans.com.ar”, asunto1, cuerpoMail);
//Aqui usa el método send del objeto sender
sender.send(mail, accion.getTransaccionID());
Lo que realiza este script es enviar un mail a la dirección indicada en el código, con el asunto y el cuerpo indicado.
La idea es que el mail informe al Gerente de compras que tiene pendiente una Orden de Compra para firmar.
Una vez ejecutada esta actividad, la cual se realiza automáticamente, el proceso queda en la actividad Autorizar OC Nivel 1.
El xml de dicha actividad es:
<?xml version="1.0" encoding="UTF-8"?>Este xml muestra un selector al accionar la actividad con las opciones “Aprobar”, “Rechazar” y “Modificar”.
Luego, sigue la compuerta Autoriza1? que tiene el siguiente script:
// importación de librerías
import app.bsuite.transacciones.operacion.OperacionHLP;
import app.bsuite.transacciones.operacion.model.OperacionVO;
import faf.app.base.security.session.model.SessionVO;
// declaración de variables y objetos
String sessionID = params.getSessionID();
UtilsHLP utils = new UtilsHLP(sessionID);
DBHelper dbh = params.getDBHelper();
// Soporte para operar con funciones básicas
BPMServiceHLP bpm = new BPMServiceHLP(sessionID, dbh);
CasoBPMAccionVO accion = params.get(“Accion”);
TransactionHLP transaction = new TransactionHLP(sessionID, dbh);
Integer estado = new Integer(0);
BigDecimal valorMaximo= new BigDecimal(“20000”);
//if que setea estado si evaluación no está vacío
if(!utils.isEmpty(accion.getAtributo(“Evaluacion”).getValor())) {
estado = new Integer(accion.getAtributo(“Evaluacion”).getValor());
}
else {
accion.setCancelada();
}
//declaracion y seteo de Orden de Compra
OperacionVO OC = OperacionHLP.getByPrimaryKey(new OperacionVO(sessionID), accion.getTransaccionID(), dbh, false);
//declaración y seteo de importe en la moneda principal
BigDecimal cotizacion = OperacionHLP.getCotizacion(dbh, accion.getTransaccionID(), OC.getMonedaID());
BigDecimal importe=BSuiteClientFunctions.getCambioMonedaLocal(OC.getImporteTotal(),cotizacion, dbh);
//Hay 2 If , el primer if controla la respuesta que ingresó el usuario en el XML
// el segundo if evalúa el monto del pedido
if( Integer.valueOf(1).equals(estado) ) {
//utiliza el método firmar para que la transacción no pueda editarse
transaction.firmar(accion.getTransaccionID());
// compareTo es lo mismo que 20000-importe . Si esa resta es < 0 es lo mismo que decir que importe > 20000
if (valorMaximo.compareTo(importe)<=0 ) {
//entra aqui si el pedido>20000
//bifurca a la actividad “Autorizar OC Nivel 2”
bpm.bifurcarHacia(accion, “Autorizar OC Nivel 2”);
//setea el valor 0 al campo Evaluacion de TPCASO
accion.getAtributo(“Evaluacion”).setValor(0);
}
else {
//bifurca a la actividad “Enviar OC Proveedor”
bpm.bifurcarHacia(accion, “Enviar OC Proveedor”);
}
}
else if( Integer.valueOf(2).equals(estado) ) {
bpm.bifurcarHacia(accion, “Notificar Solicitante”);
}
else if( Integer.valueOf(3).equals(estado) ) {
//utiliza el método desfirmar para permitir la edición de la transacción
transaction.desfirmar(accion.getTransaccionID());
accion.getAtributo(“Evaluacion”).setValor(0);
bpm.bifurcarHacia(accion, “Modificar OC”);
}
Este paso, primero, chequea cual opción ingresó el usuario:
-
En caso de haber elegido 1 (Aprobar) , la primera acción es firmar la Orden de Compra. Después, pregunta si el valor de la OC es mayor al monto indicado que en este caso es $20.000. En ese caso bifurca el caso a la actividad “Autorizar OC Nivel 2”. Si es menor a ese monto, o sea, en caso contrario, bifurca hacia “Enviar OC Proveedor”.
-
En caso que el usuario haya elegido 2 (Rechazar), el proceso seguirá con la actividad “Notificar Solicitante”.
-
Si se hubiese elegido la opción 3 (Modificar), lo que realiza es script es desfirmar la OC y luego ir a la actividad “Modificar OC”.
La actividad Modificar OC es una tarea manual que no tiene script y tampoco xml. Una vez modificada la OC se deberá ir al caso para accionarla y volver a la actividad de autorización.
La actividad Autorizar OC Nivel 2 tiene el mismo xml que la actividad Autorizar OC Nivel 1 y pregunta exactamente lo mismo.
La siguiente compuerta Autoriza2?, la única diferencia que tiene con respecto a la otra compuerta es que no pregunta por ningún monto, sólo realiza las acciones con respecto a la opción que haya seleccionado el usuario. El script es el siguiente:
// importación de librerías
import app.bsuite.transacciones.operacion.OperacionHLP;
import app.bsuite.transacciones.operacion.model.OperacionVO;
// declaración de variables y objetos
String sessionID = params.getSessionID();
UtilsHLP utils = new UtilsHLP(sessionID);
DBHelper dbh = params.getDBHelper();
BPMServiceHLP bpm = new BPMServiceHLP(sessionID, dbh);
CasoBPMAccionVO accion = params.get(“Accion”);
TransactionHLP transaction = new TransactionHLP(sessionID, dbh);
Integer estado = new Integer(0);
//if que setea estado si evaluación no está vacío
if(!utils.isEmpty(accion.getAtributo(“Evaluacion”).getValor())) {
estado = new Integer(accion.getAtributo(“Evaluacion”).getValor());
}
else {
accion.setCancelada();
}
if( Integer.valueOf(1).equals(estado) ) {
bpm.bifurcarHacia(accion, “Enviar OC Proveedor”);
}
else if( Integer.valueOf(2).equals(estado) ) {
bpm.bifurcarHacia(accion, “Notificar Solicitante”);
}
else if( Integer.valueOf(3).equals(estado) ) {
//utiliza el método desfirmar para permitir la edición de la transacción
transaction.desfirmar(accion.getTransaccionID());
accion.getAtributo(“Evaluacion”).setValor(0);
bpm.bifurcarHacia(accion, “Modificar OC”);
}
Las actividades Enviar OC Proveedor y Notificar Solicitante son actividades de tipo manual que deben ser accionadas por el usuario.
Recepcionar OC es una actividad de gestión externa. Se va a accionar una vez creado el documento que esté configurado en el workflow correspondiente.
Esta configuración se realiza de la siguiente manera:
Se debe tener la transacción que inicia ese proceso (OC) en una línea como sólo destino:
Se tiene que vincular la Orden de Compra con Seguimiento con la Recepción de Compra con Seguimiento y seleccionar el nombre del proceso que se está utilizando y el nombre de la actividad de gestión externa.
La compuerta que le sigue a la actividad de recepción es “Completa?”. Esta compuerta se fija si la recepción se hizo por la totalidad ingresada en la Orden de Compra o si le quedaron ítems pendientes. En caso de estar completamente vinculada, bifurca hacia el fin del proceso.
En cambio, si tiene ítems pendientes, vuelve a la actividad de recepción hasta que se registre la totalidad de la orden de compra.
El script de dicha compuerta es este:
import app.bsuite.transacciones.operacion.OperacionHLP;
import app.bsuite.transacciones.operacion.model.OperacionVO;
import app.bsuite.transacciones.operacion.model.OperacionItemProductoVO;
String sessionID = params.getSessionID();
DBHelper dbh = params.getDBHelper();
CasoBPMAccionVO accion = params.get(“Accion”);
BPMServiceHLP bpm = new BPMServiceHLP(sessionID, dbh);
UtilsHLP utils = new UtilsHLP(sessionID); /* Soporte para operar con funciones básicas */
OperacionVO op = OperacionHLP.getByPrimaryKey(new OperacionVO(sessionID), accion.getTransaccionID(), dbh, false);
BigDecimal pendienteAAplicar = new BigDecimal(“0”);
for(OperacionItemProductoVO item : op.getOperacionItems()) {
BigDecimal cdo = item.getCantidadDisponibleOrigen();
if(cdo!=null){
pendienteAAplicar = pendienteAAplicar.add(cdo);
}
}
if (pendienteAAplicar.compareTo(BigDecimal.ZERO) == 0) {
bpm.bifurcarHacia(accion, “Fin”);
}
else {
bpm.bifurcarHacia(accion, “Recepcionar OC”);
}