Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Transacciones + PDO

Estas en el tema de Transacciones + PDO en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Holo expertos de la web, veran en este momento tengo la necesidad de registrar una factura de venta y como sabran para esto hay que ...
  #1 (permalink)  
Antiguo 17/11/2011, 18:02
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 1 mes
Puntos: 52
Transacciones + PDO

Holo expertos de la web, veran en este momento tengo la necesidad de registrar una factura de venta y como sabran para esto hay que actualizar inventario, registrar venta, etc, este es el codigo PHP que tengo:

Código PHP:
Ver original
  1. //Funcion que registra una VENTA y luego envia al PDF que tiene el formato de la FACTURA
  2.     public function registrarVenta()
  3.     {    
  4.         //Estado de la factura cancelada o pendiente   
  5.         $_POST['fpago']     == 0 ? $estado = 0 : $estado = 1;
  6.         $estado             == 0 ? $formaPago = 'Credito' : $formaPago = 'Contado';
  7.  
  8.         //Consulto tipo de regimen de la empresa para calcular IVA
  9.         $consultaEmpresa    = $this->db->query("SELECT tipoempr FROM tb_empresa WHERE codiempr = 1");
  10.         $tipoEmpresa        = $consultaEmpresa->fetchColumn();
  11.        
  12.         //Consulto codigo de la factura
  13.         $consultaFactura    = $this->db->query("SELECT MAX(codivent) FROM tb_ventas"); 
  14.         $codigoVenta        = $consultaFactura->fetchColumn() + 1;
  15.        
  16.         //Consulto cantidad de productos para facturar
  17.         $consultaTemporales = $this->db->query("SELECT * FROM tb_temporales_vendidos");
  18.        
  19.         foreach($consultaTemporales as $temporal):
  20.  
  21.             //Comprubo que las variables no esten vacios de ser asi inserto en la tabla tb_det_ventas
  22.             $registrarDetalle           = $this->db->prepare("INSERT INTO tb_det_ventas (codivent, codiprod, cantprod, valoprod) VALUES (?,?,?,?)");
  23.             $registrarDetalle->execute(array($codigoVenta, $temporal['codiprod'], $temporal['cantprod'], $temporal['valoprod']));
  24.  
  25.             $consultaCantidadProductos  = $this->db->prepare("SELECT cantprod FROM tb_productos WHERE cobaprod = ?");
  26.             $consultaCantidadProductos->execute(array($temporal['codiprod']));
  27.             $cantidadActual             = $consultaCantidadProductos->fetchColumn();
  28.  
  29.             //Actualizo la cantidad de producto del inventario
  30.             $nuevaCantidadProductos = $this->db->prepare("UPDATE tb_productos SET cantprod = ? WHERE cobaprod = ?");
  31.             $nuevaCantidadProductos->execute(array(($cantidadActual - $temporal['cantprod']), $temporal['codiprod']));
  32.            
  33.             $subtotal += ($temporal['cantprod'] * $temporal['valoprod']);
  34.            
  35.         endforeach;//Finaliza for  
  36.        
  37.         $_POST['descuento_fijo'] == '' ? $descuento = (($_POST['descuento_porcentaje']/100) * $subtotal) : $descuento = $_POST['descuento_fijo'];
  38.  
  39.         //Calculo total parcial que es el resultado del subtotal - el descuento
  40.         $totalParcial = ($subtotal - $descuento);
  41.        
  42.         //Calculo el IVA del total bruto que es el 16%
  43.         $tipoEmpresa == 1 ? $iva = ($totalParcial * (16/100)) : $iva = 0;
  44.        
  45.         //Calculo TOTAL FINAL
  46.         $totalFinal = ($totalParcial + $iva);
  47.  
  48.         //Calculo pendiente
  49.         $estado == 0 ? $pendiente = $totalFinal : $pendiente = 0;
  50.  
  51.         //Inserto en la tabla el registro de facturas
  52.         $registrarVenta = $this->db->prepare("INSERT INTO tb_ventas (codiclie, codivend, subtvent, ivavent, descvent, totavent, saldvent, fopavent, estavent, fechvent, vencvent) VALUES (?,?,?,?,?,?,?,?,?,?,?)");
  53.         $registrarVenta->bindParam(1, $_POST['cliente'], PDO::PARAM_INT);
  54.         $registrarVenta->bindParam(2, $_POST['vendedor'], PDO::PARAM_INT);
  55.         $registrarVenta->bindParam(3, ceil($subtotal), PDO::PARAM_INT);
  56.         $registrarVenta->bindParam(4, ceil($iva), PDO::PARAM_INT);
  57.         $registrarVenta->bindParam(5, ceil($descuento), PDO::PARAM_INT);
  58.         $registrarVenta->bindParam(6, ceil($totalFinal), PDO::PARAM_INT);
  59.         $registrarVenta->bindParam(7, ceil($pendiente), PDO::PARAM_INT);
  60.         $registrarVenta->bindParam(8, $estado, PDO::PARAM_INT);
  61.         $registrarVenta->bindParam(9, $estado, PDO::PARAM_INT);
  62.         $registrarVenta->bindParam(10, date("Y-m-d", time()), PDO::PARAM_STR);
  63.         $registrarVenta->bindParam(11, $_POST['vencimiento'], PDO::PARAM_STR);
  64.         $registrarVenta->execute();

Me ha pasado en algun momento que al llegar al paso de registrar la venta (despues de haber actualizado el inventario) me vota error...

Lo que quiero es que si todo sale bien que se haga todo el trabajo con la BD de lo contrario que deje todo como estaba, he leido sobre transaccion con PDO pero no termino de entender como adaptarlo a mi necesidad, espero puedan orientarme donde debo iniciar la transaccion y donde evaluar si todo salio correcto para hacer el commit() o el rollback()

Espero me puedan ayudar, gracias.
__________________
Aprendiendo!!!
  #2 (permalink)  
Antiguo 17/11/2011, 21:05
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Respuesta: Transacciones + PDO

Si usas PDO ya tienes ese control, solo engloba todas tus operaciones en un try/catch, antes de iniciar registra el beginTransaction() y al finalizar tu try haces el commit, en el bloque catch pones el rollback.
  #3 (permalink)  
Antiguo 22/11/2011, 19:19
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 1 mes
Puntos: 52
Respuesta: Transacciones + PDO

Gracias GatorV por tu repuesta, he hecho un ejemplo con trasacciones leyendo un ejemplo del manual de PHP, he probado este ejemplo en dos BD's diferentes Postgres y MySQL y algo diferente paso en cada una de esas BD's, les cuento:

En Postgres:
Código PHP:
Ver original
  1. foreach($consultaTemporales as $temporal):
  2. *
  3. * * * * * * //Comprubo que las variables no esten vacios de ser asi inserto en la tabla tb_det_ventas
  4. * * * * * * $registrarDetalle * * * * * = $conn->prepare("INSERT INTO tb_det_ventas (codivent, codiprod, cantprod, valoprod) VALUES (?,?,?,?)");
  5. * * * * * * $registrarDetalle->execute(array($codigoVenta, $temporal['codiprod'], $temporal['cantprod'], $temporal['valoprod']));
  6. * * * * endforeach;//Finaliza for

En este ciclo como pueden ver hay una inserción a la base de datos, con las transacciones intente asi como 3 veces y hasta que se realizo la inserción pues el autoincremento o serial subio de 1 a 3 es decir se salto 2 como si los intentos que realizaba si hubieran afectado la tabla.

De igual manera para esta parte de codigo:

Código PHP:
Ver original
  1. //Inserto en la tabla el registro de facturas
  2. * * * * $registrarVenta = $conn->prepare("INSERT INTO tb_ventas (codiclie, codivend, subtvent, ivavent, descvent, totavent, saldvent, fopavent, estavent, fechvent, vencvent) VALUES (?,?,?,?,?,?,?,?,?,?,?)");
  3. * * * * $registrarVenta->bindParam(1, $_POST['cliente'], PDO::PARAM_INT);
  4. * * * * $registrarVenta->bindParam(2, $_POST['vendedor'], PDO::PARAM_INT);
  5. * * * * $registrarVenta->bindParam(3, ceil($subtotal), PDO::PARAM_INT);
  6. * * * * $registrarVenta->bindParam(4, ceil($iva), PDO::PARAM_INT);
  7. * * * * $registrarVenta->bindParam(5, ceil($descuento), PDO::PARAM_INT);
  8. * * * * $registrarVenta->bindParam(6, ceil($totalFinal), PDO::PARAM_INT);
  9. * * * * $registrarVenta->bindParam(7, ceil($pendiente), PDO::PARAM_INT);
  10. * * * * $registrarVenta->bindParam(8, $estado, PDO::PARAM_INT);
  11. * * * * $registrarVenta->bindParam(9, $estado, PDO::PARAM_INT);
  12. * * * * $registrarVenta->bindParam(10, date("Y-m-d", time()), PDO::PARAM_STR);
  13. * * * * $registrarVenta->bindParam(11, $_POST['vencimiento'], PDO::PARAM_STR);
  14. * * * * $registrarVenta->execute();

El codigo de la factura que es un consecutivo pues salto de 1 a tres.

En MySQL: En MySQL paso lo siguiente

Código PHP:
Ver original
  1. foreach($consultaTemporales as $temporal):
  2. *
  3. * * * * * * //Comprubo que las variables no esten vacios de ser asi inserto en la tabla tb_det_ventas
  4. * * * * * * $registrarDetalle * * * * * = $conn->prepare("INSERT INTO tb_det_ventas (codivent, codiprod, cantprod, valoprod) VALUES (?,?,?,?)");
  5. * * * * * * $registrarDetalle->execute(array($codigoVenta, $temporal['codiprod'], $temporal['cantprod'], $temporal['valoprod']));
  6. * * * * endforeach;//Finaliza for

En este ciclo los registros si se insertaron.

Código PHP:
Ver original
  1. //Inserto en la tabla el registro de facturas
  2. * * * * $registrarVenta = $conn->prepare("INSERT INTO tb_ventas (codiclie, codivend, subtvent, ivavent, descvent, totavent, saldvent, fopavent, estavent, fechvent, vencvent) VALUES (?,?,?,?,?,?,?,?,?,?,?)");
  3. * * * * $registrarVenta->bindParam(1, $_POST['cliente'], PDO::PARAM_INT);
  4. * * * * $registrarVenta->bindParam(2, $_POST['vendedor'], PDO::PARAM_INT);
  5. * * * * $registrarVenta->bindParam(3, ceil($subtotal), PDO::PARAM_INT);
  6. * * * * $registrarVenta->bindParam(4, ceil($iva), PDO::PARAM_INT);
  7. * * * * $registrarVenta->bindParam(5, ceil($descuento), PDO::PARAM_INT);
  8. * * * * $registrarVenta->bindParam(6, ceil($totalFinal), PDO::PARAM_INT);
  9. * * * * $registrarVenta->bindParam(7, ceil($pendiente), PDO::PARAM_INT);
  10. * * * * $registrarVenta->bindParam(8, $estado, PDO::PARAM_INT);
  11. * * * * $registrarVenta->bindParam(9, $estado, PDO::PARAM_INT);
  12. * * * * $registrarVenta->bindParam(10, date("Y-m-d", time()), PDO::PARAM_STR);
  13. * * * * $registrarVenta->bindParam(11, $_POST['vencimiento'], PDO::PARAM_STR);
  14. * * * * $registrarVenta->execute();

Aqui el consecutivo siguio correctamente es decir 1, 2, 3,etc...

Cave resaltar que en ninguna de las BD's se insertaron los registros hasta que no hubo conflictos, es decir las trasacciones funcionaron de maravilla, pero como les cuento es pasa en las Bases de Datos que utilice, alguien me puede explicar porque pasa eso?

Gracias.
__________________
Aprendiendo!!!
  #4 (permalink)  
Antiguo 22/11/2011, 22:59
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 17 años, 11 meses
Puntos: 2135
Respuesta: Transacciones + PDO

Eso ya es problema de cada RDBMS, y deberías de checar, al parecer PostgreSQL sí afectan los campos auto numericos cuando haces la transacción.
  #5 (permalink)  
Antiguo 23/11/2011, 10:13
Avatar de maycolalvarez
Colaborador
 
Fecha de Ingreso: julio-2008
Ubicación: Caracas
Mensajes: 12.120
Antigüedad: 15 años, 8 meses
Puntos: 1532
Respuesta: Transacciones + PDO

el problema es que postgres utiliza secuencias (sequence), a no ser que definas el campo como SERIAL
__________________
¡Por favor!: usa el highlight para mostrar código
El que busca, encuentra...
  #6 (permalink)  
Antiguo 23/11/2011, 17:52
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 1 mes
Puntos: 52
Respuesta: Transacciones + PDO

Cita:
Iniciado por maycolalvarez Ver Mensaje
el problema es que postgres utiliza secuencias (sequence), a no ser que definas el campo como SERIAL
Que pasa si defino el campo como SERIAL?
__________________
Aprendiendo!!!
  #7 (permalink)  
Antiguo 24/11/2011, 09:05
Avatar de maycolalvarez
Colaborador
 
Fecha de Ingreso: julio-2008
Ubicación: Caracas
Mensajes: 12.120
Antigüedad: 15 años, 8 meses
Puntos: 1532
Respuesta: Transacciones + PDO

Cita:
Iniciado por anacona16 Ver Mensaje
Que pasa si defino el campo como SERIAL?
Postgres lo genera como un entero y le crea automáticamente un sequence implicito, es prácticamente como el AutoIncrement en MySql, pero de igual forma dependes del sequence aunque postgres se encarga de incrementarlo en cada insert por tí
__________________
¡Por favor!: usa el highlight para mostrar código
El que busca, encuentra...
  #8 (permalink)  
Antiguo 24/11/2011, 17:44
Avatar de anacona16  
Fecha de Ingreso: marzo-2010
Ubicación: Bogota DC
Mensajes: 610
Antigüedad: 14 años, 1 mes
Puntos: 52
Respuesta: Transacciones + PDO

Ok, muchas gracias por sus comentarios y sugerencias.
__________________
Aprendiendo!!!

Etiquetas: pdo, php, select, transacciones
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:20.