Example #1
0
class RegistrarCobroRemito(CRUDWidget, Ui_vtnRegistrarCobroRemito):

    def __init__(self, mdi):
        """
            Constructor de la clase RegistrarCobroRemito
        :param mdi:
        :return:
        """
        MdiWidget.__init__(self, mdi)
        self.sesion = self.mdi().window().getSesionBD()
        self.validadores()
        self.cargar_obras()
        self.tableObras.hide()
        self.lineRazonSocial.setEnabled(False)
        self.btnBuscarOs.setEnabled(False)
        self.tableRemitos.setEnabled(False)

        self.rbtnRazonSocial.pressed.connect(self.habilitarObras)
        self.tableObras.itemDoubleClicked.connect(self.cargarLineObra)
        self.btnBuscarOs.pressed.connect(self.buscarObra)
        self.lineRazonSocial.returnPressed.connect(self.buscarObra)
        self.btnBuscarRemito.pressed.connect(self.buscarRemito)
        self.btnAgregar.pressed.connect(self.agregarRemito)
        self.lineNumero.returnPressed.connect(self.buscarRemito)
        self.btnAceptar.pressed.connect(self.confirmarOperacion)
        self.btnCancelar.pressed.connect(self.cancelarOperacion)

        self.obraSocialSeleccionada=None
        self.factura=None
        self.remitosAgregados=0
        self.detallesAgregados=0
        self.remitoActual=None
        self.remitosCobrados=[]
        self.importeTotal=0
        self.itemsDeFactura = []
        self.detallesFactura = []

    def buscarObra(self):
        """
            Busca las obras sociales solicitadas por el usuario
        :return:
        """
        if self.lineRazonSocial.isEnabled():
            obra_social = str(self.lineRazonSocial.text())
            data = self.getAllTabla(self.tableObras)
            if obra_social != "":
                data_temp = filter(lambda x: x[0].upper() == obra_social.upper(), data.values())
            else:
                data_temp = data.values()
            for dato in data:
                self.tableObras.setRowHidden(dato,False)
            for dato in data:
                if not data[dato] in data_temp:
                    self.tableObras.setRowHidden(dato,True)
        elif self.remitosAgregados != 0 :
            QtGui.QMessageBox.information(self,"Aviso","Hay remitos agregados. Imposbile cambiar de Obra Social")
        else:
            self.lineRazonSocial.setEnabled(True)

    def cargarLineObra(self):
        """
            Establece el valor del line de obra de acuerdo con
            lo seleccionado por el cliente.
        :return:
        """
        if self.lineRazonSocial.isEnabled():
            itemActual=self.tableObras.currentItem()
            razonSocial=str(self.tableObras.item(itemActual.row(),0).text())
            self.obraSocialSeleccionada=razonSocial
            self.lineRazonSocial.setText(razonSocial)
            self.lineRazonSocial.setEnabled(False)
        else:
            QtGui.QMessageBox.warning(self,"Advertencia","Ya se ha seleccionado una obra social")

    def habilitarObras(self):
        """
            Muestra todas las Obras Sociales habilitadas,
            de acuerdo a si existe factura o no.
        :return:
        """
        if self.factura!=None:
            QtGui.QMessageBox.information(self,"Aviso","Ya existe una factura. "
                                                       "No se puede modificar la obra social")
        else:
            if not self.rbtnRazonSocial.isChecked():
                self.btnBuscarOs.setEnabled(True)
                self.lineRazonSocial.setEnabled(True)
                self.tableObras.setVisible(True)
            else:
                self.lineRazonSocial.clear()
                self.btnBuscarOs.setEnabled(False)
                self.lineRazonSocial.setEnabled(False)
                self.tableObras.setVisible(False)
                self.obraSocialSeleccionada=None

    def validadores(self):
        """
            Setea los validadores correspondientes para
            los campos de la ventana
        :return:
        """
        ##Esta parte analiza los campos requeridos para el cliente
        camposRequeridos = [ getattr(self, "lineRazonSocial") ]
        ValidarDatos.setValidador(camposRequeridos)
        camposRequeridos = [ getattr(self, "lineNumero") ]
        ValidarDatos.setValidador(camposRequeridos)

    def cargar_obras(self):
        """
            Carga todas las Obras Sociales disponibles
        :return:
        """
        self.cargarObjetos(self.tableObras,
            ObraSocialModel.buscarTodos("razon_social", self.sesion).all(),
            ("razon_social", "cuit", "direccion")
        )

    def buscarRemito(self):
        """
            Busca el remito ingresado por el usuario. Si existe carga los detalles
            del mismo. Si existe pero ya fue cobrado o si no existe, se le notifica
            al usuario.
        :return:
        """

        if self.lineNumero.isEnabled():
            numeroRemito=self.lineNumero.text()
            if len(numeroRemito)==0:
                QtGui.QMessageBox.information(self,"Aviso","No se ha ingresado numero de remito")
            else:
                self.remitoActual = RemitoModel.existeRemito(int(numeroRemito),self.sesion)
                if self.remitoActual== None:
                    QtGui.QMessageBox.warning(self,"Aviso","El remito ingresado no existe")
                elif self.remitoActual.getCobrado() == True:
                    QtGui.QMessageBox.information(self,"Aviso","El remito ya ha sido cobrado")
                elif self.remitoActual in self.remitosCobrados:
                    QtGui.QMessageBox.information(self,"Aviso","El remito ya ha sido agregado a la factura")
                else:
                    detallesRemitos=RemitoModel.buscarDetalles(int(numeroRemito),self.sesion)
                    self.limpiarTabla(self.tableRemitos)
                    self.cargarObjetos(self.tableRemitos,
                        detallesRemitos,("producto","cantidad")
                    )
                    importes=[]
                    for a in detallesRemitos:
                        for b in self.sesion.query(ProductoModel).filter(ProductoModel.codigo_barra==a.producto):
                            importes.append(b.importe * a.cantidad)
                    for row in range(0,self.tableRemitos.rowCount()):
                        self.tableRemitos.setItem(row, 2, QtGui.QTableWidgetItem(str(importes[row])))
                    self.lineNumero.setEnabled(False)
        else:
            self.lineNumero.clear()
            self.lineNumero.setEnabled(True)
            self.limpiarTabla(self.tableRemitos)

    def obtenerValoresTabla(self,tabla):
        """
            Obtiene un arreglo que contiene arreglos
            que representan los valores de cada row
        :param tabla :
        :return:
        """
        values=[]
        for row in range(0,tabla.rowCount()):
            valuesItem=[]
            for col in range(0,tabla.columnCount()):
                valuesItem.append(tabla.item(row,col).text())
            values.append(valuesItem)
        return values

    def armarItemFactura(self,itemRemito,obraSocial,nroFactura,nroLinea):
        """
            Arma el Item de la Factura correspondiente a un Item
            del Remito seleccionado por el usuario
        :param itemRemito Arreglo con los valores de un item del Remito actual:
        :param obraSocial Obra Social seleccionada por el usuario:
        :param nroFactura Numero de Factura Actual:
        :param nroLinea Numero de Linea de la Factura Actual:
        :return:
        """
        producto=str(itemRemito[0])
        cantidad=str(itemRemito[1])
        importe=str(itemRemito[2])
        if obraSocial==None:
            descuento=0
        else:
            descuento=obraSocial.getDescuento(producto,self.sesion)
        subtotal=(float(importe)*(1-descuento))
        detalleFactura=DetalleFacturaModel(nroFactura,producto,cantidad,subtotal,descuento,nroLinea)
        detalleFactura.guardar(self.sesion)
        self.detallesFactura.append(detalleFactura)
        itemFactura=[str(producto),str(cantidad),("%.2f" % subtotal),str(descuento)]
        self.itemsDeFactura.append(itemFactura)
        return itemFactura

    def mostrarTotal(self):
        """
            Actualiza el label de Importe total, mostrando
            lo que se debe cobrar
        :return:
        """
        subtotales=[]
        for row in range(0,self.tableFactura.rowCount()):
            subtotales.append(float(self.tableFactura.item(row,2).text()))
        self.lblImporteTotal.setText("Importe Total: $%.2f" % sum(subtotales))
        self.importeTotal=sum(subtotales)

    def agregarRemito(self):
        """
            Agrega el remito seleccionado por el usuario
            a un arreglo de Remitos por cobrar.
        :return:
        """
        if self.tableRemitos.rowCount()==0:
            QtGui.QMessageBox.information(self,"Aviso","No se ha seleccionado remito para agregar")
        else:
            if self.remitosAgregados==0:
                self.factura=FacturaModel(FacturaModel.generarNumero(self.sesion))
                self.factura.guardar(self.sesion)
            self.remitosAgregados+=1
            if self.obraSocialSeleccionada == None:
                obraSocial = None
            else:
                obraSocial=ObraSocialModel.getObraSocial(self.obraSocialSeleccionada,self.sesion)
            for row,item in enumerate(self.obtenerValoresTabla(self.tableRemitos)):
                self.tableFactura.insertRow(row)
                self.detallesAgregados+=1
                for col,value in enumerate(self.armarItemFactura(item,obraSocial,self.factura.numero,self.detallesAgregados)):
                    self.tableFactura.setItem(row,col,QtGui.QTableWidgetItem(str(value)))
            self.remitosCobrados.append(self.remitoActual)
            self.mostrarTotal()
            self.limpiarTabla(self.tableRemitos)
            self.lineNumero.setEnabled(True)
            self.lineNumero.clear()

    def limpiarForm(self):
        """
            Limpia la ventana una vez que se finalizó
            la operación.
        :return:
        """
        self.detallesFactura = []
        self.remitosCobrados = []
        self.itemsDeFactura = []
        self.remitosAgregados=0
        self.detallesAgregados=0
        self.factura=None
        self.remitoActual=None
        self.importeTotal=0
        self.limpiarTabla(self.tableFactura)
        self.limpiarTabla(self.tableRemitos)
        self.lineRazonSocial.clear()
        self.lineNumero.clear()
        self.lineNumero.setEnabled(True)
        self.rbtnRazonSocial.setChecked(False)
        self.tableObras.hide()
        self.lblImporteTotal.setText("Importe Total: $0.00")

    def confirmarOperacion(self):
        """
            Verifica si el cliente acepta la operación realizada.
            Si acepta genera la factura correspondiente, si no deshace lo
            realizado.
        :return:
        """

        if self.remitosAgregados == 0:
            QtGui.QMessageBox.information(self,"Aviso","No se ha realizado ningun cobro")
        else:
            efectivo,ok=QtGui.QInputDialog.getDouble(self,"Importe a pagar",("El importe a pagar es: $%.2f" % self.importeTotal),0,0,2000,2)
            if ok:
                if float(efectivo) < self.importeTotal:
                    QtGui.QMessageBox.information(self,"Aviso","El importe ingresado es menor al total")
                else:
                    QtGui.QMessageBox.information(self,"Cambio","Su vuelto es: $%.2f" % (float(efectivo)-self.importeTotal))
                    for remito in self.remitosCobrados:
                        remito.setCobrado(self.factura.numero)
                        remito.modificar(self.sesion)
                    cobroCliente=CobroClienteModel(CobroClienteModel.obtenerNumero(self.sesion),self.factura.numero,"Efectivo",self.importeTotal)
                    cobroCliente.guardar(self.sesion)
                    self.factura.setObra(self.obraSocialSeleccionada)
                    self.factura.modificar(self.sesion)
                    QtGui.QMessageBox.information(self,"Venta","El cobro ha sido exitoso")
                    self.objectModified.emit()
                    data = {}
                    data["numero"] = self.factura.numero
                    data["fecha"] = self.factura.fecha_emision
                    data["detalles"] = self.itemsDeFactura
                    data["formaPago"] = "Efectivo"
                    generarFactura(data)

                    self.limpiarForm()

    def cancelarOperacion(self):
        """
            Marca a todos los remitos afectados como No Cobrados
            cuando el usuario indica que quiere cancelar la operacion
        :return:
        """

        ok = QtGui.QMessageBox.warning(self,"Aviso",QtCore.QString.fromUtf8("¿Desea cancelar la operacion?"),\
                                       QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Ok)
        if ok == QtGui.QMessageBox.Ok:
            if self.factura != None:
                self.factura.anular()
                self.factura.modificar(self.sesion)
            for detalle in self.detallesFactura:
                detalle.borrar(self.sesion)
            self.limpiarForm()

    def cancelarVentana(self):

        if self.factura != None:
            self.factura.anular()
            self.factura.modificar(self.sesion)
        for detalle in self.detallesFactura:
                detalle.borrar(self.sesion)
        self.limpiarForm()
Example #2
0
class VentaContado(CRUDWidget, Ui_vtnVentaContado):

    """
        Clase encargada de modelar el comportamiento de Venta al Contado

    """

    def __init__(self,mdi):
        """
            Constructor de la clase VentaContado
        :param mdi:
        :return:
        """
        MdiWidget.__init__(self, mdi)
        self.sesion = self.mdi().window().getSesionBD()
        self.validadores()
        self.cargar_obras()
        self.lineMedicamento.returnPressed.connect(self.buscarProd)
        self.lineMonodroga.returnPressed.connect(self.buscarProd)
        self.lineCuit.returnPressed.connect(self.buscarObra)
        self.lineObra.returnPressed.connect(self.buscarObra)
        self.tableObra.itemDoubleClicked.connect(self.cargarObra)
        self.tableProductos.itemDoubleClicked.connect(self.agregarProducto)
        self.btnBuscar.pressed.connect(self.limpiarObra)
        self.btnAceptar.pressed.connect(self.confirmarOperacion)
        self.btnCancelar.pressed.connect(self.cancelarOperacion)
        self.btnEliminar.pressed.connect(self.eliminarDetalle)
        self.rbtnObra.pressed.connect(self.habilitarObras)
        self.btnBuscar.setEnabled(False)
        self.tableObra.setVisible(False)
        self.lineCuit.setEnabled(False)
        self.lineObra.setEnabled(False)
        self.cargarProductosSinObra()
        self.productosAgregados=0
        self.lotesVentas={}
        self.facturaCobrada=False
        self.obraSocialSeleccionada=None
        self.formapago = None
        self.factura = None
        self.data = {}
        self.detallesTabla = {}

    def buscarProd(self):
        """
            Filtra la tabla de Productos de acuerdo
            a los criterios de busqueda impuestos
        :return:
        """
        medicamento = str(self.lineMedicamento.text())
        monodroga = str(self.lineMonodroga.text())
        data = self.getAllTabla(self.tableProductos)

        if medicamento != "":
            dataMedic = filter(lambda x: x[1].upper() == medicamento.upper(), data.values())
        else:
            dataMedic = data.values()
        if monodroga != "":
            dataMono = filter(lambda x: x[3].upper() == monodroga.upper(), dataMedic)
        else:
            dataMono = dataMedic

        for dato in data:
            self.tableProductos.setRowHidden(dato,False)

        for dato in data:
            if not data[dato] in dataMono:
                self.tableProductos.setRowHidden(dato,True)

    def buscarObra(self):
        """
            Filtra la tabla de Obras Sociales de acuerdo
            a los criterios de busqueda impuestos
        :return:
        """
        razon_social = str(self.lineObra.text())
        cuit = str(self.lineCuit.text())
        data = self.getAllTabla(self.tableObra)

        if razon_social != "":
            dataRazon = filter(lambda x: x[0].upper() == razon_social.upper(), data.values())
        else:
            dataRazon = data.values()
        if cuit != "":
            dataCuit = filter(lambda x: x[1].upper() == cuit.upper(), dataRazon)
        else:
            dataCuit = dataRazon

        for dato in data:
            self.tableObra.setRowHidden(dato,False)

        for dato in data:
            if not data[dato] in dataCuit:
                self.tableObra.setRowHidden(dato,True)

    def actualizar(self):
        """
            Actualiza la informacion de la
            tabla de Productos
        :return:
        """
        if self.obraSocialSeleccionada!=None:
            self.cargar_productos(self.obraSocialSeleccionada)
        else:
            self.cargarProductosSinObra()

    def habilitarObras(self):
        """
            Muestra las Obras Sociales si no hay una factura creada.
            Si la factura ya se encuentra creada, notifica que no
            es posible cambiar la Obra Social actual.
        :return:
        """
        if self.productosAgregados != 0:
            QtGui.QMessageBox.information(self,"Aviso","Ya se han agregado productos a la factura")
        else:
            if not self.rbtnObra.isChecked():
                self.btnBuscar.setEnabled(True)
                self.lineObra.setEnabled(True)
                self.lineCuit.setEnabled(True)
                self.tableObra.setVisible(True)
            else:
                self.lineObra.clear()
                self.lineCuit.clear()
                self.btnBuscar.setEnabled(False)
                self.lineObra.setEnabled(False)
                self.lineCuit.setEnabled(False)
                self.tableObra.setVisible(False)
                self.obraSocialSeleccionada=None
                self.cargarProductosSinObra()

    def cargarProductosSinObra(self):
        """
            Carga en la tabla de Productos todos los productos
            sin descuento de Obra Social
        :return:
        """

        self.limpiarTabla(self.tableProductos)

        ##Cnsulta para obtener todos los productos del sistema, con su correspondiente
        ##codigo de barra, monodroga, descuento, importe
        query=self.sesion.query(ProductoModel.codigo_barra,ProductoModel.id_medicamento,ProductoModel.id_presentacion,MonodrogaModel.nombre,ProductoModel.importe).\
            join(MedicamentoModel).filter(ProductoModel.id_medicamento==MedicamentoModel.nombre_comercial).\
            join(MonodrogaModel).filter(MedicamentoModel.id_monodroga==MonodrogaModel.nombre).\
            filter(ProductoModel.baja==False).order_by(ProductoModel.codigo_barra)

        ##Se cargan los datos obtenidos en la tabla de Producto
        for n, obj in enumerate(query):
            self.tableProductos.insertRow(n)
            self.tableProductos.setItem(n, 0, QtGui.QTableWidgetItem(str(obj[0])))
            self.tableProductos.setItem(n, 1, QtGui.QTableWidgetItem(str(obj[1])))
            self.tableProductos.setItem(n, 2, QtGui.QTableWidgetItem(str(obj[2])))
            self.tableProductos.setItem(n, 3, QtGui.QTableWidgetItem(str(obj[3])))
            self.tableProductos.setItem(n, 4, QtGui.QTableWidgetItem(str(0)))
            self.tableProductos.setItem(n, 5, QtGui.QTableWidgetItem(str(obj[4])))

        ##Se carga la cantidad de cada producto en la tabla
        for row,producto in enumerate(ProductoModel.buscarTodos(ProductoModel.codigo_barra,self.sesion)):
            self.tableProductos.setItem(row,6,QtGui.QTableWidgetItem(str(producto.getCantidad(self.sesion))))

    def cargar_productos(self, obraSocial):
        """
            Carga en la tabla de Productos todos los
            productos del sistema con los correspondientes descuentos
            de la Obra Social seleccionada
        :param obraSocial:
        :return:
        """
        self.limpiarTabla(self.tableProductos)

        query=self.sesion.query(ProductoModel.codigo_barra,ProductoModel.id_medicamento,ProductoModel.id_presentacion,MonodrogaModel.nombre,DescuentoModel.descuento,ProductoModel.importe).\
            join(MedicamentoModel).filter(ProductoModel.id_medicamento==MedicamentoModel.nombre_comercial).\
            join(MonodrogaModel).filter(MedicamentoModel.id_monodroga==MonodrogaModel.nombre).\
            join(DescuentoModel).filter(DescuentoModel.producto==ProductoModel.codigo_barra).\
            filter(DescuentoModel.obra_social==obraSocial,ProductoModel.baja==False).order_by(ProductoModel.codigo_barra)

        for n, obj in enumerate(query):
            self.tableProductos.insertRow(n)
            for m, campo in enumerate(obj):
                self.tableProductos.setItem(n, m, QtGui.QTableWidgetItem(str(campo)))

        for row,producto in enumerate(ProductoModel.buscarTodos(ProductoModel.codigo_barra,self.sesion)):
            self.tableProductos.setItem(row,6,QtGui.QTableWidgetItem(str(producto.getCantidad(self.sesion))))

    def cargarObra(self):
        """
            Carga la informacion de la Obra Social
            seleccionada por el usuario
        :return:
        """
        rowActual=self.tableObra.currentItem().row()
        self.lineObra.setText(str(self.tableObra.item(rowActual,0).text()))
        self.lineCuit.setText(str(self.tableObra.item(rowActual,1).text()))
        self.tableObra.hide()
        self.lineObra.setEnabled(False)
        self.lineCuit.setEnabled(False)
        self.obraSocialSeleccionada = str(self.lineObra.text())
        self.cargar_productos(self.obraSocialSeleccionada)
        self.gbProducto.setVisible(True)

    def limpiarObra(self):
        """
            Permite buscar las obras sociales si aun
            no hay ninguna seleccionada.
            Limpia los campos correspondientes a las
            Obras Sociales, si ya hay una cargada.
        :return:
        """

        if self.lineObra.isEnabled():
            self.buscarObra()
        else:
            self.lineCuit.clear()
            self.lineObra.clear()
            self.lineCuit.setEnabled(True)
            self.lineObra.setEnabled(True)
            self.tableObra.setVisible(True)

    def validadores(self):

        camposRequeridos = [getattr(self,"lineMonodroga")]
        ValidarDatos.setValidador(camposRequeridos)

        camposRequeridos = [getattr(self,"lineMedicamento")]
        ValidarDatos.setValidador(camposRequeridos)

    def cargar_obras(self):
        """
            Carga todos las obras Sociales en el sistema
            en la tabla de Obras Sociales
        :return:
        """
        self.cargarObjetos(self.tableObra,
            ObraSocialModel.buscarTodos("razon_social", self.sesion).all(),
            ("razon_social", "cuit", "direccion")
        )

    def descontarCantidad(self,detalle,producto,cantidad):
        """
            Actualiza el stock en una determinada cantidad,
            de un producto dado
        :param detalle Detalle de la Factura :
        :param producto Codigo de barra del producto:
        :param cantidad Cantidad a descontar:
        :return:
        """
        query=LoteModel.obtenerLoteProducto(producto,self.sesion)
        valores=[]
        for a in query:
            loteProducto=LoteProductoModel.buscarLoteProducto(self.sesion,producto,a.codigo).first()
            if cantidad<=loteProducto.cantidad:
                loteProducto.descontarCantidad(cantidad)
                loteProducto.modificar(self.sesion)
                valores.append([loteProducto,cantidad])
                break
            else:
                cantidad-=loteProducto.cantidad
                valores.append([loteProducto,loteProducto.cantidad])
                loteProducto.descontarCantidad(loteProducto.cantidad)
                loteProducto.modificar(self.sesion)
        self.lotesVentas[detalle]=valores
        detalle.agregarLotes(self.sesion,self.lotesVentas[detalle])

    def agregarProducto(self):
        """
            Agrega un producto seleccionada a la Factura
        :return:
        """
        itemActual=self.tableProductos.currentItem()
        cantidad, ok = QtGui.QInputDialog.getInt(self,"Cantidad","Ingrese cantidad del producto",1,1,2000,5)
        if not ok:
            self.showMsjEstado("No se ha seleccionado cantidad del producto")
        else:
            cantidadProducto=int(self.tableProductos.item(itemActual.row(),6).text())
            if cantidad>cantidadProducto:
                QtGui.QMessageBox.information(self,"Aviso","La cantidad ingresada es mayor que la del stock")
            else:
                if self.productosAgregados == 0 and self.factura == None:
                    self.factura=FacturaModel(FacturaModel.generarNumero(self.sesion))
                    self.factura.guardar(self.sesion)
                self.productosAgregados+=1
                rowItemActual=itemActual.row()
                rows=self.tableFactura.rowCount()
                self.tableFactura.insertRow(rows)

                #--Carga de items en la tabla--*
                producto = int(self.tableProductos.item(rowItemActual,0).text())
                importeActual=float(self.tableProductos.item(rowItemActual,5).text())
                descuentoActual=float(self.tableProductos.item(rowItemActual,4).text())
                subtotal=importeActual*(1-descuentoActual)
                ####-------------------------#####
                detalleFactura=DetalleFacturaModel(self.factura.numero,producto,cantidad,
                    subtotal*cantidad,descuentoActual,self.productosAgregados
                )
                self.descontarCantidad(detalleFactura,producto,cantidad)
                self.tableFactura.setItem(rows,0,QtGui.QTableWidgetItem(str(detalleFactura.producto)))
                self.tableFactura.setItem(rows,1,QtGui.QTableWidgetItem(str(detalleFactura.cantidad)))
                self.tableFactura.setItem(rows, 2, QtGui.QTableWidgetItem(str("%.2f"%(subtotal*cantidad))))

                detalleFactura.guardar(self.sesion)
                self.detallesTabla[rows] = detalleFactura

                self.data[rows] = [
                    producto, cantidad, subtotal*cantidad, descuentoActual
                ]

                self.actualizar()
                self.objectModified.emit()

    def eliminarDetalle(self):
        """
            Elimina el detalle seleccionado por el usuario y actualiza
            el stock del producto en particular.
        :return:
        """

        itemActual = self.tableFactura.currentItem()
        if itemActual == None:
            self.showMsjEstado("Debe seleccionar un item para dar de baja")
        else:
            detalle = self.detallesTabla[itemActual.row()]
            for loteVenta in self.lotesVentas[detalle]:
                loteVenta[0].aumentarCantidad(loteVenta[1])
                loteVenta[0].modificar(self.sesion)
            detalle.eliminarLotesAsociados(self.sesion)
            detalle.bajaFisica(self.sesion)
            del self.lotesVentas[detalle]
            del self.data[itemActual.row()]
            self.tableFactura.hideRow(itemActual.row())
            self.actualizar()
            self.productosAgregados -=1
            self.objectModified.emit()

    def limpiarVentana(self):
        """
            Limpia la ventana actual
        :return:
        """

        self.productosAgregados=0
        self.lotesVentas={}
        self.facturaCobrada=False
        self.obraSocialSeleccionada=None
        self.formapago = None
        self.factura = None
        self.data = {}
        self.detallesTabla = {}
        self.lineObra.clear()
        self.lineObra.setEnabled(True)
        self.lineCuit.clear()
        self.lineCuit.setEnabled(True)
        self.tableObra.setVisible(False)
        self.rbtnObra.setChecked(False)
        self.limpiarTabla(self.tableProductos)
        self.limpiarTabla(self.tableFactura)
        self.cargarProductosSinObra()

    def calcularTotal(self):
        """
            Calcula el total a pagar
        :return Total a Pagar:
        """
        subtotales=[]
        for row in range(0,self.tableFactura.rowCount()):
            subtotales.append(float(self.tableFactura.item(row,2).text()))
        importeTotal=sum(subtotales)
        return importeTotal

    def confirmarOperacion(self):
        """
            Confirma la operacion si todo ha sido exitoso.
            De lo contrario notifica que la Factura todavia no ha sido
            cobrada o que no se efectuo ninguna venta
        :return:
        """
        if self.productosAgregados == 0:
            QtGui.QMessageBox.information(self,"Aviso","No se ha agregado ningun producto")
        else:
            ventana = Cobrar(self,self.calcularTotal(),self.factura,self.sesion)
            ventana.exec_()
            if self.facturaCobrada:
                QtGui.QMessageBox.information(self,"Venta","La venta se ha realizado con exito")
                data = {}
                data["numero"] = self.factura.numero
                data["fecha"] = self.factura.fecha_emision
                data["detalles"] = self.data.values()
                data["formaPago"] = self.formapago
                generarFactura(data)
                self.factura.setObra(self.obraSocialSeleccionada)
                self.factura.modificar(self.sesion)
                self.limpiarVentana()
            else:
                QtGui.QMessageBox.information(self,"Aviso","La factura aun no ha sido cobrada")

    def cancelarOperacion(self):
        """
            Cancela la operacion actual, y reestablece
            los stocks a sus valores originales
        :return:
        """

        ok=QtGui.QMessageBox.warning(self,"Aviso","¿Desea cancelar la operación?",\
                                     QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Ok)
        if ok == QtGui.QMessageBox.Ok:
            if self.factura != None:
                self.factura.anular()
            for detalle in self.lotesVentas:
                for loteVenta in self.lotesVentas[detalle]:
                    loteVenta[0].aumentarCantidad(loteVenta[1])
                    loteVenta[0].modificar(self.sesion)
                detalle.eliminarLotesAsociados(self.sesion)
                detalle.borrar(self.sesion)
            self.objectModified.emit()
            self.limpiarVentana()

    def cancelarVentana(self):

        if self.factura != None:
            self.factura.anular()
        for detalle in self.lotesVentas:
            for loteVenta in self.lotesVentas[detalle]:
                loteVenta[0].aumentarCantidad(loteVenta[1])
                loteVenta[0].modificar(self.sesion)
            detalle.eliminarLotesAsociados(self.sesion)
            detalle.borrar(self.sesion)
        self.objectModified.emit()
        self.limpiarVentana()

    def addHandlerSignal(self):

        self.sender = PoolOfWindows.getVentana("VentaConRemito")
        self.sender.objectModified.connect(self.actualizar)
        self.sender1 = PoolOfWindows.getVentana("AltaProducto")
        self.sender1.objectCreated.connect(self.actualizar)
        self.sender2 = PoolOfWindows.getVentana("BajaProducto")
        self.sender2.objectDeleted.connect(self.actualizar)
        self.sender3 = PoolOfWindows.getVentana("ModificarProducto")
        self.sender3.objectModified.connect(self.actualizar)
        self.sender4 = PoolOfWindows.getVentana("DevolucionDeCliente")
        self.sender4.objectModified.connect(self.actualizar)
        self.sender5 = PoolOfWindows.getVentana("ModificarRemito")
        self.sender5.objectModified.connect(self.actualizar)
        self.sender6 = PoolOfWindows.getVentana("BajaRemito")
        self.sender6.objectModified.connect(self.actualizar)
        self.sender7 = PoolOfWindows.getVentana("FraccionarProducto")
        self.sender7.objectModified.connect(self.actualizar)
        self.sender8 = PoolOfWindows.getVentana("AltaLote")
        self.sender8.objectCreated.connect(self.actualizar)
        self.sender9 = PoolOfWindows.getVentana("ModificarLote")
        self.sender9.objectModified.connect(self.actualizar)