Error al crear Usuario desde Ci

Hola buenos dias, tengo una operación en donde permite crear un usuario, esta operación es publica.
La operación funciona bien en el ambiente de desarrollo, pero cuando regenero el proyecto en produccion me salta el siguiente error.

 exception "toba_error_db" with message "SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "apex_usuario" does not exist LINE 1: INSERT INTO apex_usuario ( usuario, nombre, autentificacion,... ^" in /usr/local/toba/2.6/php/lib/db/toba_db.php:566 Stack trace: #0 /usr/local/toba/2.6/php/modelo/toba_modelo_instancia.php(1392): toba_db->sentencia_ejecutar(0, Array) #1 /usr/local/toba/2.6/php/nucleo/lib/toba_instancia.php(673): toba_modelo_instancia->agregar_usuario("36036036", "XXX  YYYY...", "XXXX", NULL, Array) #2 /usr/local/toba/2.6/proyectos/dj_unlar/php/usuarios/ci_usuarios.php(108): toba_instancia->agregar_usuario("36036036", "XXX  YYYY", "XXXXX", Array) #3 /usr/local/toba/2.6/proyectos/dj/php/usuarios/ci_usuarios.php(18): ci_usuarios->set_usuarios() #4 /usr/local/toba/2.6/php/nucleo/componentes/interface/toba_ci.php(282): ci_usuarios->evt__procesar("undefined") #5 /usr/local/toba/2.6/php/nucleo/componentes/interface/toba_ci.php(204): toba_ci->disparar_evento_propio() #6 /usr/local/toba/2.6/php/nucleo/toba_solicitud_web.php(135): toba_ci->disparar_eventos() #7 /usr/local/toba/2.6/php/nucleo/toba_solicitud_web.php(55): toba_solicitud_web->procesar_eventos() #8 /usr/local/toba/2.6/php/nucleo/toba_nucleo.php(79): toba_solicitud_web->procesar() #9 /usr/local/toba/2.6/proyectos/dj/www/aplicacion.php(24): toba_nucleo->acceso_web() #10 {main}
 SQLSTATE[25P02]: In failed sql transaction: 7 ERROR: current transaction is aborted, commands ignored until end of transaction block Más info...

El código del ci es el siguiente

 
class ci_usuarios extends dj_ci {

    protected $s__usuario;

    function ini() {
        $this->s__usuario = array();
    }

    //---- Eventos ----------------------------------------------------------------------
    function evt__procesar() {
        $this->set_usuarios();
    }

    //---- formulario -------------------------------------------------------------------
    function conf__formulario(dj_unlar_ei_formulario $form) {
        if (count($this->s__usuario) > 0) {
            $form->set_datos($this->s__usuario);
        }
    }

    function evt__formulario__modificacion($datos) {
        if (strnatcasecmp($datos['documento'], $datos['clave']) == 0) {
            throw new toba_error('La clave no debe ser igual al DNI.');
        }

        if (strnatcasecmp($datos['email'], $datos['email2']) > 0) {
            throw new toba_error('Verifique que haya ingresado correctamente su email');
        }
        $datos['apellido'] = strtoupper($datos['apellido']);
        $datos['nombre'] = strtoupper($datos['nombre']);
        $this->s__usuario = $datos;
    }

    
    function set_usuarios() {
        $bloq = toba::instancia()->es_usuario_bloqueado($this->s__usuario['documento']);
        if ($bloq) {
            toba::notificacion()->agregar('El usuario se encuentra bloqueado. 
 
				Contactese con la Subsecretaria de Recursos Humanos');
        }

        $this->dep('datos')->persistidor()->desactivar_transaccion();
        toba::db()->abrir_transaccion();
        try {
            $ins = co_inscripciones::existe_inscripcion($this->s__usuario['documento'], $this->s__usuario['id_convocatoria']);
            if (count($ins) > 0) {
                throw new toba_error('"<b>Ya existe un usuario en la convocatoria actual. </b>
Comuniquese con la Subsecretaria de Recursos Humanos"');
            } else {
                $usuario = $this->s__usuario;
                $user = toba::usuario()->existe_usuario($usuario['documento']);
                if (!$user) {
                    //$db_toba = toba_instancia::instancia()->get_db();
                    try {
                        $username = addslashes($usuario['documento']);

                        $nombre = $usuario['apellido'] . ' ' . $usuario['nombre'];
                        $param = array("email" => $usuario['email'], "parametro_a" => $usuario['documento']);
                        toba::instancia()->agregar_usuario($username, $nombre, $usuario['clave'], $param);
                        toba::instancia()->vincular_usuario('dj_unlar', $username, 'agente');
                        $user = $username;
                    } catch (toba_error $e) {
                        $user = null;
                       // $db_toba->abortar_transaccion();
                        toba::notificacion()->agregar($e);
                    }
                }
                $this->dep('datos')->sincronizar();
                toba::db()->cerrar_transaccion();
                $this->dep('datos')->resetear();
                $this->set_pantalla('pant_msj');
                $this->pantalla()->set_descripcion("<strong>Los datos se grabaron correctamente.
                	
Presione \"Volver\" para regresar a la pantalla de ingreso.</strong>");
            }
        } catch (toba_error $error) {
            toba::db()->abortar_transaccion();
            throw new toba_error($error->getMessage());
        }
    }

}

toba 2.6.7
php 5.6
postgres 9.4

Hola Leo,

te hago una consulta rapida, diferencia en la organizacion de la bd entre desarrollo y produccion?.. todo en una misma base?, bases distintas?.

Otra cosa a mirar, permisos del usuario con el que la aplicacion se conecta a la bd… tiene acceso a todos los schemas/bases?

```

class ci_usuarios extends dj_ci {

protected $s__usuario;

function ini() {
    $this->s__usuario = array();
}

//---- Eventos ----------------------------------------------------------------------
function evt__procesar() {
    $this->set_usuarios();
}

//---- formulario -------------------------------------------------------------------
function conf__formulario(dj_unlar_ei_formulario $form) {
    if (count($this->s__usuario) > 0) {
        $form->set_datos($this->s__usuario);
    }
}

function evt__formulario__modificacion($datos) {
    if (strnatcasecmp($datos['documento'], $datos['clave']) == 0) {
        throw new toba_error('La clave no debe ser igual al DNI.');
    }

    if (strnatcasecmp($datos['email'], $datos['email2']) > 0) {
        throw new toba_error('Verifique que haya ingresado correctamente su email');
    }
    $datos['apellido'] = strtoupper($datos['apellido']);
    $datos['nombre'] = strtoupper($datos['nombre']);
    $this->s__usuario = $datos;
}


function set_usuarios() {
    $bloq = toba::instancia()->es_usuario_bloqueado($this->s__usuario['documento']);
    if ($bloq) {
        toba::notificacion()->agregar('El usuario se encuentra bloqueado. 

			Contactese con la Subsecretaria de Recursos Humanos');
    }

    $this->dep('datos')->persistidor()->desactivar_transaccion();
    toba::db()->abrir_transaccion();
    try {
        $ins = co_inscripciones::existe_inscripcion($this->s__usuario['documento'], $this->s__usuario['id_convocatoria']);
        if (count($ins) > 0) {
            throw new toba_error('"<b>Ya existe un usuario en la convocatoria actual. </b>

Comuniquese con la Subsecretaria de Recursos Humanos"');
} else {
$usuario = $this->s__usuario;
$user = toba::usuario()->existe_usuario($usuario[‘documento’]);
if (!$user) {
//$db_toba = toba_instancia::instancia()->get_db();
try {
$username = addslashes($usuario[‘documento’]);

                    $nombre = $usuario['apellido'] . ' ' . $usuario['nombre'];
                    $param = array("email" => $usuario['email'], "parametro_a" => $usuario['documento']);
                    toba::instancia()->agregar_usuario($username, $nombre, $usuario['clave'], $param);
                    toba::instancia()->vincular_usuario('dj_unlar', $username, 'agente');
                    $user = $username;
                } catch (toba_error $e) {
                    $user = null;
                   // $db_toba->abortar_transaccion();
                    toba::notificacion()->agregar($e);
                }
            }
            $this->dep('datos')->sincronizar();
            toba::db()->cerrar_transaccion();
            $this->dep('datos')->resetear();
            $this->set_pantalla('pant_msj');
            $this->pantalla()->set_descripcion("<strong>Los datos se grabaron correctamente.

Presione "Volver" para regresar a la pantalla de ingreso.");
}
} catch (toba_error $error) {
toba::db()->abortar_transaccion();
throw new toba_error($error->getMessage());
}
}

}

</blockquote>
Lo que no entiendo de este codigo es lo siguiente, tenes dos catch anidados para el mismo tipo de error... el interno estaria de mas, no te aborta la transaccion y permite que se continue ejecutando desde alli, con lo que va a mandar a sincronizar el datos_relacion.

Por otro lado, la llamada a toba::instancia() va a intentar crear una nueva conexion a la bd, que segun como sea la organizacion puede derivar en (reuso) otro schema (el cual hay que especificar manualmente) , u otra bd (que te tira por el piso la idea de transaccion a menos que simules un dos fases).

Si ambas bd, tanto negocio como toba estan en schemas separados, vas a tener que cambiar el schema de la conexion de forma manual ya que al reusar la conexion va a seguir apuntando al schema de negocio. Luego podes reestablecerlo explicitamente tambien, no deberia afectarte la transaccionalidad eso.

Saludos

Hola Richard, gracias por tu respuesta. al final modifique el código que puse en un principio, pero realizando los insert a mano. debido a que usando los metodos agregar_usuario y vincular_usuario me arrojaban error.

Con respecto a tus consultas.

te hago una consulta rápida, diferencia en la organización de la bd entre desarrollo y producción?.. todo en una misma base?, bases distintas?.
tanto en desarrollo y producción tienen la misma organización, y están en BD diferentes.
Otra cosa a mirar, permisos del usuario con el que la aplicacion se conecta a la bd... tiene acceso a todos los schemas/bases?
en ambos entornos estan con el usuario postgres.
Lo que no entiendo de este codigo es lo siguiente, tenes dos catch anidados para el mismo tipo de error... el interno estaria de mas, no te aborta la transaccion y permite que se continue ejecutando desde alli, con lo que va a mandar a sincronizar el datos_relacion.
Nose por que habre puesto 2 try cath anidados. pero ya elimine el try interno.

El codigo, que me funciono al final, y que mencione al principio es el siguiente, pero me quedo la duda de porque en un entorno me funciono y en el otro no.

function set_usuarios() {
        $bloq = toba::instancia()->es_usuario_bloqueado($this->s__usuario['documento']);
        if ($bloq) {
            toba::notificacion()->agregar('El usuario se encuentra bloqueado. 
 
				Contactese con la Subsecretaria de Recursos Humanos');
        }

        $this->dep('datos')->persistidor()->desactivar_transaccion();
        toba::db()->abrir_transaccion();
        try {
            $ins = co_inscripciones::existe_inscripcion($this->s__usuario['documento'], $this->s__usuario['id_convocatoria']);
            if (count($ins) > 0) {
                throw new toba_error('"<b>Ya existe un usuario en la convocatoria actual.</b>

                    Recupere su clave o 
                    Comuniquese con la Subsecretaria de Recursos Humanos"');
            } else {
                $usuario = $this->s__usuario;
                self::crear_usuario($usuario);
                $this->set_persona();
                EnviarEmail::enviar_usuario($this->s__usuario);
                $this->dep('datos')->sincronizar();
                $this->dep('datos')->resetear();
                toba::db()->cerrar_transaccion();
                $this->set_pantalla('pant_msj');
                $this->pantalla()->set_descripcion("<strong>Los datos se grabaron correctamente.
                	
Presione \"Volver\" para regresar a la pantalla de ingreso.</strong>");
            }
        } catch (toba_error $error) {
            //toba::instancia()->bloquear_usuario($this->s__usuario['documento']);
            toba::db()->abortar_transaccion();
            throw new toba_error($error->get_mensaje_log());
        }
    }
function crear_usuario($usuario) {
        try {
            $db_toba = toba_instancia::instancia()->get_db();
            $nombre = quote($usuario['apellido'] . ' ' . $usuario['nombre']);
            $username = quote(addslashes($usuario['documento']));
            $email = quote($usuario['email']);


            $algoritmo = 'bcrypt';
            $clave = encriptar_con_sal($usuario['clave'], $algoritmo);

            $sql = "INSERT INTO desarrollo.apex_usuario (usuario, nombre, clave,autentificacion,email) VALUES ($username, $nombre,'".$clave."','bcrypt',$email);";
            $db_toba->ejecutar($sql);
            $sql = "INSERT INTO desarrollo.apex_usuario_proyecto (proyecto, usuario_grupo_acc, usuario) VALUES ('dj_unlar','agente', $username);";
            $db_toba->ejecutar($sql);
        } catch (toba_error $error) {
            toba::notificacion()->agregar('error ' . $error->get_mensaje_log());
        }
    }


Hola Leo,

Esto es lo que me trae problemas, si estan en bases separadas la conexion no se reusa… por lo tanto no puede haber un “le pifie al schema” para que te diga que esa tabla no existe.
Si estan en bases diferentes, lo que me deja entrever ese error es que el usuario/rol utilizado en bases.ini no tiene permisos para alguno de los componentes en postgres, sea schema, tabla,etc.

en ambos entornos estan con el usuario postgres.
Ojo, aun cuando te conectes con postgres.. si el owner de la bd es otro y seteo permisos estrictos, no se si te deja acceder tendria que averiguar mejor esto, es dba.. pero creo que tiene que cambiarle los permisos a la bd para accederla si lo dejaron fuera en la creacion.
El codigo, que me funciono al final, y que mencione al principio es el siguiente, pero me quedo la duda de porque en un entorno me funciono y en el otro no.
Evidentemente hay alguna pequeña diferencia, muy sutil como para que se vea rapidamente... pero algo hay, de lo contrario no hubiera fallado.
```
        $sql = "INSERT INTO desarrollo.apex_usuario (usuario, nombre, clave,autentificacion,email) VALUES ($username, $nombre,'".$clave."','bcrypt',$email);";
        $db_toba->ejecutar($sql);
        $sql = "INSERT INTO desarrollo.apex_usuario_proyecto (proyecto, usuario_grupo_acc, usuario) VALUES ('dj_unlar','agente', $username);";
        $db_toba->ejecutar($sql);
</blockquote>

Ojo con eso, calificar asi la tabla va a hacer que falle la consulta en cualquier base que tenga un schema con otro nombre... de ahi el beneficio de mandarlo via toba y bases.ini.

Saludos.