Ejemplo n.º 1
0
    def createXlsReport(self):
        homepath = expanduser('~')
        filePath = self.chooseSaveFile(os.path.join(homepath, 'report.xls'), 'xls')
        if not filePath:
            return
        excelWorkbook = xlwt.Workbook()
        invoice = excelWorkbook.add_sheet("ReportExample")
        cell_middle = xlwt.easyxf("align: vert centre, horz centre, wrap on")
        cell_left = xlwt.easyxf("align: vert centre, horz left")
        cell_middle_bold = xlwt.easyxf("font: bold on; align: vert centre, horz centre, wrap on")
        cell_middle_bold_borders = xlwt.easyxf(
            "font: bold on; border: left thin, top thin, right thin, bottom thin; align: vert centre, horz centre, wrap on")
        cell_string = xlwt.easyxf(
            "border: left thin, top thin, right thin, bottom thin; align: vert centre, horz left, wrap on")
        cell_underline = xlwt.easyxf("font: underline on; align: vert centre, horz left, wrap on")
        cell_left_with_borders = xlwt.easyxf(
            "border: left thin, top thin, right thin, bottom thin; align: vert centre, horz left, wrap on")
        cell_right_with_borders = xlwt.easyxf(
            "border: left thin, top thin, right thin, bottom thin; align: vert centre, horz right, wrap on")
        invoice.write_merge(1, 1, 0, 9, u"ПРИМЕР ОТЧЕТА №1 от %s" % datetime.datetime.now().strftime('%Y-%m-%d'),
                            cell_middle_bold)
        invoice.write_merge(2, 2, 0, 9, u"Дополнительная строка  %s от %s" % ('_' * 3, '_' * 10), cell_middle_bold)

        clientQuery = QSqlQueryModel()
        clientQuery.setQuery(
            "SELECT Surname, Name, Midname, birthdate, sex, snils FROM Client where id=%s" % self.clientId)

        invoice.write(4, 0, u'ФИО пациента:', cell_left)
        invoice.write(4, 1, unicode(clientQuery.record(0).value("Surname").toString() + " " +
                                    clientQuery.record(0).value("Name").toString() + " " +
                                    clientQuery.record(0).value("Midname").toString()), cell_left)
        invoice.write(5, 0, u'Дата рождения:', cell_left)
        invoice.write(5, 1, unicode(clientQuery.record(0).value('birthdate').toString()), cell_left)
        invoice.write(6, 0, u'СНИЛС:', cell_left)
        invoice.write(6, 1, unicode(clientQuery.record(0).value('snils').toString()), cell_left)
        invoice.write(7, 0, u'Пол', cell_left)
        invoice.write(7, 1, u'М' if 1 == clientQuery.record(0).value('sex').toInt() else u'Ж', cell_left)

        clientQuery.setQuery('''SELECT distinct s.*
                                FROM Client c
                                INNER join cure cr on cr.Client_id = c.id
                                INNER join services s on s.id = cr.services_id
                                where c.id = %d''' % self.clientId)

        invoice.write_merge(9, 9, 0, 9, u"Информация об оказанных услугах", cell_middle_bold)
        invoice.write(10, 0, u'№ п/п', cell_left_with_borders)
        invoice.write(10, 1, u'Код', cell_left_with_borders)
        invoice.write_merge(10, 10, 2, 9, u"Наименование услуги", cell_left_with_borders)
        for i in xrange(clientQuery.rowCount()):
            invoice.write(11 + i, 0, i + 1, cell_left_with_borders)
            invoice.write(11 + i, 1, unicode(clientQuery.record(i).value('code').toString()), cell_left_with_borders)
            invoice.write_merge(11 + i, 11 + i, 2, 9, unicode(clientQuery.record(i).value('Name').toString()),
                                cell_left_with_borders)

        invoice.write(clientQuery.rowCount() + 12, 0, u'Дата печати:')
        invoice.write(clientQuery.rowCount() + 12, 1, datetime.datetime.now().strftime('%Y-%m-%d'))
        excelWorkbook.save(filePath)
        return
Ejemplo n.º 2
0
 def loadAllData(self):
     self.items = []
     model = QSqlQueryModel()
     model.setQuery('''SELECT s.code, s.name
             FROM services s
             ''')
     for i in xrange(model.rowCount()):
         code = model.record(i).value("code").toString()
         name = model.record(i).value("name").toString()
         item = [code + u": " + name]
         self.items.append(item)
     self.reset()
Ejemplo n.º 3
0
 def loadData(self, clientId):
     self.items = []
     if clientId:
         model = QSqlQueryModel()
         model.setQuery('''SELECT s.code, s.name
             FROM Client c
             INNER JOIN cure cr on cr.Client_ID = c.id
             INNER JOIN services s on s.id = cr.Services_ID
             WHERE c.id = {0}
             '''.format(clientId))
         for i in xrange(model.rowCount()):
             code = model.record(i).value("code").toString()
             name = model.record(i).value("name").toString()
             item = [code + u": " + name]
             self.items.append(item)
     self.items.append([u""])
     self.reset()
Ejemplo n.º 4
0
class FrmKardexOther( Ui_FrmKardexOther, Base ):
    '''
    classdocs
    '''

    def __init__( self, parent = None ):
        '''
        Constructor
        '''
        super( FrmKardexOther, self ).__init__( parent )
        self.actionNew.setEnabled( False )
        self.navmodel = QSqlQueryModel()

        self.detailsModel = QSqlQueryModel()


        self.navproxymodel = QSortFilterProxyModel()
        self.navproxymodel.setSourceModel( self.navmodel )

        self.detailsproxymodel = QSortFilterProxyModel()
        self.detailsproxymodel.setSourceModel( self.detailsModel )

        self.accountsnavmodel = QSqlQueryModel()
        self.accountsproxymodel = QSortFilterProxyModel()
        self.accountsproxymodel.setSourceModel( self.accountsnavmodel )



        self.editmodel = None

        if not self.user.hasRole( "contabilidad" ):
            self.tableaccounts.setVisible( False )
            self.lblaccounts.setVisible( False )

        QTimer.singleShot( 0, self.loadModels )

    def setControls( self, status ):
        if self.user.hasRole( "contabilidad" ):
            self.actionNew.setEnabled( True )
            self.dtPicker.setReadOnly( False )


        self.actionPrint.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )

        self.actionNew.setVisible( status )
        self.actionPreview.setVisible( status )

        self.actionCancel.setVisible( not status )
        self.actionSave.setVisible( not status )

        self.swConcept.setCurrentIndex( 0 if status else 1 )
        self.swWarehouse.setCurrentIndex( 0 if status else 1 )
        self.tabnavigation.setEnabled( status )

        self.txtObservations.setReadOnly( status )

        self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers if status else QAbstractItemView.AllEditTriggers )


        if not status:
            self.tabWidget.setCurrentIndex( 0 )
            self.tabledetails.addAction( self.actionDeleteRow )



        else:
            self.tabledetails.removeAction( self.actionDeleteRow )

            self.tabledetails.setModel( self.detailsproxymodel )
            self.tablenavigation.setModel( self.navproxymodel )
            self.tableaccounts.setModel( self.accountsproxymodel )


        self.tabledetails.setColumnHidden( IDARTICULO, True )
        self.tabledetails.setColumnHidden( IDDOCUMENTOD, True )

        self.tableaccounts.setColumnHidden( IDDOCUMENTOC, True )
        self.tableaccounts.setColumnHidden( IDCUENTA, True )


        self.tabledetails.setColumnWidth( DESCRIPCION, 300 )

        self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
        self.tablenavigation.setColumnHidden( ESTADO, True )
        self.tablenavigation.setColumnHidden( OBSERVACIONES, True )


    def addActionsToToolBar( self ):
        if self.user.hasRole( "contabilidad" ):
            self.toolBar.addActions( [
                self.actionNew,
                self.actionPreview,
                self.actionPrint,
                self.actionSave,
                self.actionCancel
            ] )
        else:
            self.toolBar.addActions( [
                self.actionPreview,
                self.actionPrint,
            ] )
        self.toolBar.addSeparator()
        self.toolBar.addActions( [
            self.actionGoFirst,
            self.actionGoPrevious,
            self.actionGoLast,
            self.actionGoNext,
            self.actionGoLast
        ] )
        if self.user.hasRole( "kardex" ): #si el usuario no es de kardex no deberia de poder dar entrada a bodega
            self.actionGiveEntry = self.createAction( 
                                                     text = "Dar entrada al documento",
                                                    icon = QIcon.fromTheme( 'dialog-ok-apply', QIcon( ":/icons/res/dialog-ok-apply.png" ) ),
                                                     slot = self.giveEntry )
            self.toolBar.addActions( [
                self.actionGiveEntry
            ] )
    def giveEntry( self ):
        """
        Dar entrada a un kardex
        """
        if QMessageBox.question( self, qApp.organizationName(),
                                 u"¿Realmente desea dar entrada a este documento?",
                                  QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
            iddoc = self.navmodel.record( self.mapper.currentIndex() ).value( IDDOCUMENTO ).toInt()[0]


            query = QSqlQuery()
            try:
                if not self.database.isOpen():
                    if not self.database.open():
                        raise UserWarning( u"No se pudo conectar con la"\
                                           + " base de datos" )

                if not self.database.transaction():
                    raise Exception( u"No se pudo iniciar la transacción "\
                                     + "para confirmar el kardex" )

                q = """
                UPDATE documentos d SET idestado = %d  
                WHERE d.iddocumento = %d LIMIT 1
                """ % ( constantes.CONFIRMADO, iddoc )
                if not query.exec_( q ):
                    raise Exception( u"No se pudo actualizar el estado "\
                                     + "del documento" )

                if not query.exec_( """
                    INSERT INTO documentos (ndocimpreso, fechacreacion,
                     idtipodoc, total, idtipocambio, idbodega)
                    SELECT fnConsecutivo(%d,NULL), NOW(), %d, total, 
                    idtipocambio, idbodega FROM documentos
                    WHERE iddocumento = %d;
                """ % ( constantes.IDKARDEX,
                        constantes.IDKARDEX,
                        iddoc ) ):
                    raise Exception( u"No se pudo insertar el documento kardex" )

                insertedId = query.lastInsertId().toInt()[0]

                if not query.exec_( """
                    INSERT INTO docpadrehijos (idpadre, idhijo) VALUES (%d, %d)
                """ % ( iddoc, insertedId ) ):
                    raise Exception( u"No se pudo crear la relación entre el"\
                                     + " documento ajuste de bodega y su kardex" )

                if not self.database.commit():
                    raise Exception( u"No se pudo hacer commit" )
                QMessageBox.information( self, qApp.organizationName(),
                                          "El documento se ha guardado con exito" )
                self.updateModels()
            except UserWarning as inst:
                logging.error( unicode( inst ) )
                self.database.rollback()
                QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
            except Exception as inst:
                logging.critical( unicode( inst ) )
                self.database.rollback()
                QMessageBox.critical( self, qApp.organizationName(),
                                      u"No se pudo confirmar la entrada"\
                                      + " de este documento" )




    def deleteRow( self ):
        """
        Funcion usada para borrar lineas de la tabla
        """
        index = self.tabledetails.currentIndex()

        if not index.isValid():
            return
        row = index.row()

        self.editmodel.removeRows( row, 1 )

    def updateModels( self ):
        try:
            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.database().open:
                    raise UserWarning( "No se pudo conectar con la base datos" )

            query = """
            SELECT
                d.iddocumento,
                d.ndocimpreso AS 'Ndoc',
                d.fechacreacion,
                d.observacion,
                b.nombrebodega AS 'Bodega',
                d.total AS 'Total',
                d.idestado,
                c.descripcion AS 'Concepto',
                IF( dph.idhijo IS NULL, 1, 0) AS 'Pendiente'
            FROM documentos d
            JOIN bodegas b ON b.idbodega = d.idbodega
            JOIN conceptos c ON c.idconcepto = d.idconcepto
            LEFT JOIN docpadrehijos dph ON dph.idpadre = d.iddocumento
            LEFT JOIN documentos kardex ON dph.idhijo = kardex.iddocumento AND kardex.idtipodoc = %d
            WHERE d.idtipodoc = %d
            """ % ( constantes.IDKARDEX, constantes.IDAJUSTEBODEGA )
            self.navmodel.setQuery( query )
            query = """
            SELECT
                a.idarticulo,
                a.descripcion,
                axd.costounit,
                axd.unidades,
                axd.iddocumento
            FROM vw_articulosdescritos a
            JOIN articulosxdocumento axd ON axd.idarticulo = a.idarticulo
            JOIN documentos d ON d.iddocumento = axd.iddocumento AND d.idtipodoc = %d
            LEFT JOIN docpadrehijos dph ON dph.idhijo = d.iddocumento
            WHERE dph.idhijo IS NULL
            """ % constantes.IDAJUSTEBODEGA
            self.detailsModel.setQuery( query )


            if self.user.hasAnyRole( ["inventario", "contabilidad"] ):
                query = """
                SELECT
                    cc.idcuenta,
                    cc.codigo,
                    cc.descripcion,
                    cxd.monto,
                    cxd.iddocumento
                FROM cuentasxdocumento cxd
                JOIN documentos d ON d.iddocumento = cxd.iddocumento AND d.idtipodoc = %d
                JOIN cuentascontables cc ON cxd.idcuenta = cc.idcuenta
                """ % constantes.IDAJUSTEBODEGA
                self.accountsnavmodel.setQuery( query )

            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.txtPrintedDocumentNumber, NDOCIMPRESO )
            self.mapper.addMapping( self.txtConcept, CONCEPT )
            self.mapper.addMapping( self.txtWarehouse, BODEGA )
            self.mapper.addMapping( self.txtObservations, OBSERVACIONES )
            self.mapper.addMapping( self.dtPicker, FECHA )



        except UserWarning as inst:
            QMessageBox.critical( self,
                                  qApp.organizationName(),
                                  unicode( inst ) )
            logging.error( unicode( inst ) )
        except Exception as inst:
            QMessageBox.critical( self,
                                  qApp.organizationName(),
                                  u"No se pudo iniciar un nuevo ajuste de kardex" )

            logging.critical( unicode( inst ) )


    def updateDetailFilter( self, index ):
        curr_id = self.navmodel.record( index ).value( IDDOCUMENTO ).toInt()[0]

        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOD )
        self.detailsproxymodel.setFilterRegExp( "^%d$" % curr_id )

        self.accountsproxymodel.setFilterKeyColumn( IDDOCUMENTOC )
        self.accountsproxymodel.setFilterRegExp( "^%d$" % curr_id )

        if self.user.hasRole( 'kardex' ):
            estado = self.navmodel.record( index ).value( PENDIENTE ).toInt()[0]
            self.actionGiveEntry.setVisible( estado == 1 )

    def newDocument( self ):
        try:
            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.database().open:
                    raise UserWarning( "No se pudo conectar con la "\
                                       + "base de datos" )

            self.editmodel = KardexOtherModel()

            self.editmodel.uid = self.user.uid

            conceptosmodel = QSqlQueryModel()
            conceptosmodel.setQuery( """
            SELECT
            	c.idconcepto,
            	c.descripcion
            FROM conceptos c
            WHERE c.idtipodoc = %d
            """ % constantes.IDAJUSTEBODEGA )

            if conceptosmodel.rowCount() == 0:
                raise UserWarning( u"No existen conceptos para los "\
                                   + "ajustes de bodega" )

            self.cbConcept.setModel( conceptosmodel )
            self.cbConcept.setModelColumn( 1 )

            warehouseModel = QSqlQueryModel()
            warehouseModel.setQuery( """
            SELECT idbodega, nombrebodega
            FROM bodegas b
            ORDER BY idbodega
            """ )

            self.cbWarehouse.setModel( warehouseModel )
            self.cbWarehouse.setModelColumn( 1 )

            #Calcular el numero de kardex
            query = QSqlQuery( """
            CALL spConsecutivo(%d,NULL);
            """ % constantes.IDAJUSTEBODEGA )
            if not query.exec_():
                raise UserWarning( "No se pudo calcular el numero "\
                                   + "del kardex" )

            query.first()
            self.editmodel.printedDocumentNumber = query.value( 0 ).toString()
            self.txtPrintedDocumentNumber.setText( self.editmodel.printedDocumentNumber )




            articlesmodel = QSqlQueryModel()
            articlesmodel.setQuery( """
            SELECT
                a.idarticulo,
                a.descripcion,
                ca.valor as costo
            FROM vw_articulosdescritos a
            JOIN costosarticulo ca ON a.idarticulo = ca.idarticulo AND ca.activo = 1
            """ )

            delegate = KardexOtherDelegate( articlesmodel )
            self.tabledetails.setItemDelegate( delegate )
            self.tabledetails.setModel( self.editmodel )

            accountsdelegate = AccountsSelectorDelegate( QSqlQuery( """
             SELECT c.idcuenta, c.codigo, c.descripcion
             FROM cuentascontables c
             JOIN cuentascontables p ON c.padre = p.idcuenta AND p.padre != 1
             WHERE c.padre != 1 AND c.idcuenta != 22
             """ ), True )
            self.tableaccounts.setItemDelegate( accountsdelegate )

            self.tableaccounts.setModel( self.editmodel.accountsmodel )

            self.editmodel.accountsmodel.insertRows( 0, 2 )

            line = AccountsSelectorLine()
            line.itemId = int( movimientos.INVENTARIO )
            line.code = "110 003 001 000 000"
            line.name = "INV Inventario de Bodega"

            self.editmodel.accountsmodel.lines[0] = line

            self.addLine()
            self.dtPicker.setDateTime( QDateTime.currentDateTime() )
            self.status = False
        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
            self.status = True
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(), "El sistema no pudo iniciar una nueva entrada de kardex" )
            self.status = True


    def cancel( self ):
        u"""
        Borrar todos los modelos que se hallan creado para el modo edición,
        asignar los modelos de navegación a las vistas
        """
        self.editmodel = None
        self.tabledetails.setModel( self.detailsproxymodel )
        self.status = True

    @pyqtSlot( int )
    @if_edit_model
    def on_cbWarehouse_currentIndexChanged( self, index ):
        self.editmodel.warehouseId = self.cbWarehouse.model().index( index, 0 ).data().toInt()[0]

    @pyqtSlot( int )
    @if_edit_model
    def on_cbConcept_currentIndexChanged( self, index ):
        self.editmodel.conceptId = self.cbConcept.model().index( index, 0 ).data().toInt()[0]
Ejemplo n.º 5
0
class FrmPersona( Ui_frmPersona, Base ):
    def __init__( self, tipo, rol, parent ):
        super( FrmPersona, self ).__init__( parent, True )

        self.tabledetails = None
        self.setWindowModality( Qt.WindowModal )
        self.setWindowFlags( Qt.Dialog )

        self.tipo = tipo
        self.rol = rol
        self.lbltitulo.setText( u"<B>Datos del %s</B>" % rol )

        self.editmodel = None
#        self.parent = parent

        self.navmodel = QSqlQueryModel()

        self.navproxymodel = QSortFilterProxyModel()
        self.navproxymodel.setFilterKeyColumn( -1 )
        self.navproxymodel.setSourceModel( self.navmodel )
        self.navproxymodel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.tablenavigation.setModel( self.navproxymodel )

        self.actionPreview.setVisible( False )
        self.actionPrint.setVisible( False )
        self.updateModels()
        self.status = True

    def updateDetailFilter( self, index ):
        self.actionEditar.setEnabled( self.navproxymodel.rowCount() > 0 )
        if self.navmodel.record( index ).value( "activo" ).toBool():
            self.rbactivo.setChecked( True )
        else:
            self.rbinactivo.setChecked( True )

    def updateModels( self ):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( "No se pudo abrir la base de datos" )

            #TODO: Esta consulta tiene que mejorar para definir realmente quien es el que realiza el arqueo
            query = u"""
            SELECT
                tipopersona,
                idpersona,
                Nombre,
                direccion as 'Dirección',
                telefono as 'Teléfono',
                email as 'E-mail',
                ruc as Ruc,
                activo
            FROM personas p
            WHERE tipopersona =%d
            """ % self.tipo
            self.navmodel.setQuery( query )
            self.navproxymodel.setSourceModel( self.navmodel )

            self.actionEditar.setEnabled( self.navproxymodel.rowCount() > 0 )

            self.tablenavigation.setModel( self.navproxymodel )

            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )
            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.txtnombre, NOMBRE )
            self.mapper.addMapping( self.txtdireccion, DIRECCION )
            self.mapper.addMapping( self.txttelefono, TELEFONO )
            self.mapper.addMapping( self.txtcorreo, CORREO )
            self.mapper.addMapping( self.txtruc, RUC )



            self.tablenavigation.setColumnHidden( TIPO, True )
            self.tablenavigation.setColumnHidden( ID, True )
            self.tablenavigation.setColumnHidden( ACTIVO, True )

            self.tablenavigation.setColumnWidth( NOMBRE, 200 )

            self.navigate( 'last' )

#            self.mapper.setCurrentIndex( index.row() )

        except UserWarning as inst:
            logging.error( inst )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        except Exception as inst:
            logging.critical( inst )
        finally:
            if self.database.isOpen():
                self.database.close()


    def save( self ):
        editado = self.status == 2

        titulo = "Guardar los cambios" if editado else "Crear un nuevo %s" % self.rol

        if self.txtnombre.text() == "":
            self.txtnombre.setFocus()
            QMessageBox.warning( None, titulo, "Por favor escriba el nombre del %s" % self.rol )
            return False


        if QMessageBox.question( None, titulo, u"¿Está seguro que desea guardar los cambios?" if editado else u"¿Está seguro que desea crear al %s?" % self.rol , QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No:
            return False

        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo conectar con la base de datos" )

            query = QSqlQuery()

            pos = self.mapper.currentIndex()
            if editado:
                query.prepare( """
                UPDATE personas SET 
                direccion =:dir, 
                telefono=:tel,
                email=:correo,
                ruc=:ruc, 
                tipopersona = :tipo,
                activo=:activo
                WHERE 
                idpersona = :idpersona 
                LIMIT 1;
                """ )
                query.bindValue( ":idpersona", self.navmodel.record( self.mapper.currentIndex() ).value( "idpersona" ).toInt()[0] )
            else:
                query.prepare( """
                INSERT INTO personas(nombre,fechaingreso,direccion,telefono,email,ruc,tipopersona,activo) VALUES
                (:nombre,NOW(),:dir,:tel,:correo,:ruc,:tipo,:activo)
                """ )
                query.bindValue( ":nombre", self.txtnombre.text() )

            query.bindValue( ":dir", self.txtdireccion.text() )
            query.bindValue( ":tel", self.txttelefono.text() )
            query.bindValue( ":correo", self.txtcorreo.text() )
            query.bindValue( ":ruc", self.txtruc.text() )
            query.bindValue( ":tipo", self.tipo )
            query.bindValue( ":activo", 1 if self.rbactivo.isChecked() else 0 )


            if not query.exec_():
                raise Exception( query.lastError().text() )

            QMessageBox.information( None, titulo, "Los cambios fueron guardados" if editado else "El %s fue creado exitosamente" % self.rol )

            self.updateModels()
            self.status = True
            result = True
            if editado:
                self.mapper.setCurrentIndex( pos )

        except UserWarning as inst:
            logging.error( unicode( inst ) )
            logging.error( query.lastError().text() )
            QMessageBox.critical( self, titulo, unicode( inst ) )
            result = False
        except Exception as inst:
            logging.critical( unicode( inst ) )
            logging.critical( query.lastError().text() )
            QMessageBox.critical( self, titulo, "El %s no pudo ser creado" % self.rol )
            result = False
        finally:
            if self.database.isOpen():
                self.database.close()

        return result

    def cancel( self ):
        self.editmodel = None

        self.status = True
        self.navigate( 'last' )

    def addActionsToToolBar( self ):
        self.actionEditar = self.createAction( 
                                  text = "Editar",
                                  tip = u"Editar la persona",
                                  icon = QIcon.fromTheme( 'document-edit', QIcon( ":/icons/res/document-edit.png" ) ),
                                  slot = functools.partial( self._setStatus, 2 ) )
        self.toolBar.addActions( [
            self.actionEditar
        ] )

        super( FrmPersona, self ).addActionsToToolBar()


    def setControls( self, status ):
        if status == 2 and self.navproxymodel.rowCount() == 0:
            return

        if status == False:
            self.txtnombre.setText( "" )
            self.txtnombre.setFocus()
            self.txtdireccion.setText( "" )
            self.txtcorreo.setText( "" )
            self.txtruc.setText( "" )
            self.txttelefono.setText( "" )
            self.rbactivo.setChecked( True )
            self.txtnombre.setReadOnly( False )
        elif status == True:
            self.tablenavigation.setFocus()
            self.txtnombre.setReadOnly( True )
        else:
            self.txtdireccion.setFocus()
            status = False
        self.tabWidget.setCurrentIndex( 0 if status == False else 1 )

        self.rbactivo.setEnabled( not status )
        self.rbinactivo.setEnabled( not status )
        self.tablenavigation.setEnabled( status )
        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionCancel.setVisible( not status )
        self.actionSave.setVisible( not status )
        self.actionEditar.setVisible( status )

        self.actionGoFirst.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoPrevious.setVisible( status )

        self.txtcorreo.setReadOnly( status )
        self.txtdireccion.setReadOnly( status )
        self.txtruc.setReadOnly( status )
        self.txttelefono.setReadOnly( status )



    def newDocument( self ):
        self.status = False





    @pyqtSlot( int )
    def on_cbnombre_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        index = self.combomodel.mapToSource( self.combomodel.index( index, 0 ) )
        index = index.row()
        self.personaId = self.personasModel.record( index ).value( "idpersona" ).toInt()[0]
        self.txtcorreo.setText( self.personasModel.record( index ).value( "email" ).toString() )
        self.txtdireccion.setText( self.personasModel.record( index ).value( "direccion" ).toString() )
        self.txtruc.setText( self.personasModel.record( index ).value( "ruc" ).toString() )
        self.txttelefono.setText( self.personasModel.record( index ).value( "telefono" ).toString() )

    @pyqtSlot( unicode )
    def on_txtSearch_textChanged( self, searchstring ):
        """
        Cambiar el filtro para el navigation model
        @param searchstring: Es el contenido por el cual se va a filtrar el modelo de navegación
        @type searchstring: string
        """
        self.navproxymodel.setFilterFixedString( searchstring )
Ejemplo n.º 6
0
class FrmKardex( Ui_frmKardex, Base ):
    '''
    Esta clase implementa la funcionalidad para los movimientos de entrada y 
    salida de kardex, en ella el encargado de bodega da cuenta de cuando entra
    o sale algo de bodega
    '''
    def __init__( self, tiposdoc, parent = None, edit = True ):
        '''
        Constructor
        '''
        super( FrmKardex, self ).__init__( parent )
        self.tiposdoc = ",".join( [str( item ) for item in tiposdoc] )

        self.edit = edit



        self.navigationmodel = QSqlQueryModel()

        self.detailsModel = QSqlQueryModel()


        self.navproxymodel = QSortFilterProxyModel()
        self.navproxymodel.setSourceModel( self.navigationmodel )

        self.detailsproxymodel = QSortFilterProxyModel()
        self.detailsproxymodel.setSourceModel( self.detailsModel )


        self.tabledetails.setModel( self.detailsproxymodel )
        self.tablenavigation.setModel( self.navproxymodel )

        self.editmodel = None

        QTimer.singleShot( 0, self.loadModels )


    def updateModels( self ):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"Existen problemas de conexión "\
                                       + "con la base de datos" )
            query = u"""
            SELECT
                d.iddocumento,
                CONCAT_WS(' ',tdc.descripcion, d.ndocimpreso) as 'Documento Referencia',
                kx.ndocimpreso as 'Numero Kardex',
                b.nombrebodega as 'Bodega',
                d.fechacreacion as 'Fecha',
                kx.observacion as 'Observacion Kardex',
                d.observacion as 'Observacion Doc',
                d.idbodega
            FROM documentos d
            JOIN tiposdoc tdc ON tdc.idtipodoc = d.idtipodoc
            JOIN bodegas b ON b.idbodega = d.idbodega
            JOIN docpadrehijos dpd ON dpd.idpadre = d.iddocumento
            JOIN documentos kx ON kx.iddocumento = dpd.idhijo AND kx.idtipodoc = %d
            WHERE d.idtipodoc IN (%s)
            GROUP BY d.iddocumento
            """ % ( constantes.IDKARDEX, self.tiposdoc )
            self.navigationmodel.setQuery( query )

            query = u"""
           SELECT 
                axd.idarticulo, 
                ad.descripcion as 'Articulo', 
                axd.unidades as 'Unidades',
                IF(akx.unidades > 0,    CONCAT('+',akx.unidades),     IFNULL(akx.unidades,0)) as 'Ajuste', 
                axd.iddocumento
            FROM articulosxdocumento axd
            JOIN vw_articulosdescritos ad ON ad.idarticulo = axd.idarticulo
            JOIN documentos d ON axd.iddocumento = d.iddocumento AND d.idtipodoc IN ( %s)
            JOIN docpadrehijos dph ON dph.idpadre = d.iddocumento
            JOIN documentos kardex ON kardex.iddocumento = dph.idhijo AND kardex.idtipodoc = %d
            LEFT JOIN articulosxdocumento akx ON akx.iddocumento = kardex.iddocumento
            GROUP BY ad.idarticulo, kardex.iddocumento
            """ % ( self.tiposdoc , constantes.IDKARDEX )
            self.detailsModel.setQuery( query )

            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.txtParentPrintedDocumentNumber,
                                    NDOCIMPRESO )
            self.mapper.addMapping( self.txtPrintedDocumentNumber, NKARDEX )
            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.txtWarehouse, NOMBREBODEGA )
            self.mapper.addMapping( self.txtKardexObservation,
                                    OBSERVACIONK, "plainText" )
            self.mapper.addMapping( self.txtDocObservation,
                                     OBSERVACION, "plainText" )


#            self.tabledetails.horizontalHeader().setStretchLastSection( True )
            self.tabledetails.setColumnHidden(0,True)
        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                  unicode( inst ) )
            logging.error( inst )
        except Exception as inst:
            logging.critical( inst )

    def updateDetailFilter( self, index ):
        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        self.detailsproxymodel.setFilterRegExp( "^" +
                                             self.navigationmodel.record( index
                                                           ).value( IDDOCUMENTO
                                                        ).toString() + "$" )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )


    def cancel( self ):
        self.editmodel = None
        self.tabledetails.setModel( self.detailsproxymodel )
        self.status = True

    @pyqtSlot()
    @if_edit_model
    def on_txtKardexObservation_textChanged( self ):
        self.editmodel.observations = self.txtKardexObservation.toPlainText()

    def setControls( self, status ):
        self.tabnavigation.setEnabled( status )
        self.actionPrint.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )

        self.actionNew.setVisible( status )
        self.actionPreview.setVisible( status )

        self.dtPicker.setReadOnly( status )

        self.actionCancel.setVisible( not status )
        self.actionSave.setVisible( not status )

        self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
        self.tablenavigation.setColumnHidden( OBSERVACION, True )
        self.tablenavigation.setColumnHidden( OBSERVACIONK, True )
        self.tablenavigation.setColumnHidden( BODEGA, True )

        self.tabledetails.setColumnHidden( AJUSTE, True )

        self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )
        if status:
            self.tabledetails.setEditTriggers( 
                                          QAbstractItemView.NoEditTriggers )
        else:
            self.tabledetails.setEditTriggers( 
                                          QAbstractItemView.AllEditTriggers )
        self.tabledetails.resizeColumnsToContents()
#            self.tabledetails.horizontalHeader().setStretchLastSection( True )

        self.txtKardexObservation.setReadOnly( status )

#        self.tabledetails.horizontalHeader().setStretchLastSection( True )



    def newDocument( self ):
        """
        Slot documentation goes here.
        """
        query = QSqlQuery()
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo establecer una conexión"\
                                       + " con la base de datos" )

            dlgdoc = dlgSelectDoc( self.tiposdoc )
            if dlgdoc.exec_() == QDialog.Accepted:
                self.editmodel = KardexModel()
                row = dlgdoc.tblBills.selectionModel().currentIndex().row()
                self.editmodel.parentId = dlgdoc.filtermodel.index( row, 0
                                                            ).data().toInt()[0]
                self.editmodel.uid = self.user.uid
                self.editmodel.parentPrinted = dlgdoc.filtermodel.index( row, 1
                                                             ).data().toString()
                self.editmodel.warehouseId = dlgdoc.filtermodel.index( row, 4
                                                           ).data().toInt()[0]
                self.editmodel.warehouseName = dlgdoc.filtermodel.index( row, 2
                                                          ).data().toString()

                self.txtDocObservation.setPlainText( 
                                        dlgdoc.filtermodel.index( row, 5 )
                                        .data().toString() )
                self.txtParentPrintedDocumentNumber.setText( 
                                                self.editmodel.parentPrinted )
                self.txtWarehouse.setText( self.editmodel.warehouseName )

                if not query.prepare( """
                SELECT
                    axd.idarticulo,
                    vw.descripcion,
                    axd.unidades,
                    cxa.valor
                FROM articulosxdocumento axd
                JOIN costosarticulo cxa ON cxa.idarticulo = axd.idarticulo AND cxa.activo = 1
                JOIN vw_articulosdescritos vw ON vw.idarticulo = axd.idarticulo
                WHERE axd.iddocumento = %d
                """ % self.editmodel.parentId ):
                    raise Exception( "No se pudo preparar la consulta para "\
                                     + "obtener las lineas del documento" )

                if not query.exec_():
                    raise Exception( "No se pudo ejecutar la consulta para"\
                                     + " obtener las lineas del documento" )

                if not query.size() > 0:
                    raise Exception( "La consulta para las lineas del "\
                                     + "documento no devolvio nada" )
                while query.next():
                    linea = LineaKardex()
                    linea.itemId = query.value( 0 ).toInt()[0]
                    linea.itemDescription = query.value( 1 ).toString()
                    linea.numdoc = query.value( 2 ).toInt()[0]
                    linea.itemCost = Decimal( query.value( 3 ).toString() )
                    row = self.editmodel.rowCount()
                    self.editmodel.insertRows( row )
                    self.editmodel.lines[row] = linea

#               Cargar el numero de kardex 
                query = QSqlQuery( """
               CALL spConsecutivo(%d,NULL);
                """ % constantes.IDKARDEX )

                if not query.exec_():
                    raise UserWarning( u"No se pudo calcular el numero de"\
                                       + " la devolución" )
                query.first()
                self.editmodel.printedDocumentNumber = query.value( 0 ).toString()

                self.txtPrintedDocumentNumber.setText( 
                                      self.editmodel.printedDocumentNumber )


                self.status = False
                self.tabnavigation.setEnabled( False )
                self.tabWidget.setCurrentIndex( 0 )
                self.tabledetails.setModel( self.editmodel )

                delegate = KardexDelegate()
                self.tabledetails.setItemDelegate( delegate )


                self.dtPicker.setDateTime( QDateTime.currentDateTime() )
                self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )
                self.tabledetails.resizeColumnsToContents()
        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                   unicode( inst ) )
            logging.warning( inst )
            self.cancel()
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                   "No se pudo iniciar el documento kardex" )
            logging.critical( inst )
            self.cancel()
        finally:
            if self.database.isOpen():
                self.database.close()



    def updateLabels( self ):
        pass
Ejemplo n.º 7
0
class tbFactura( QTabWidget ,Ui_tbFactura ):
    """
    Implementacion de la interfaz grafica para facturas
    """
    web = "facturas.php?doc="
    DATE_FORMAT = "dd/MM/yyyy"
    def __init__( self ):
        '''
        Constructor
        '''
        super( tbFactura, self ).__init__(  )

# ESTABLECER LA INTERFAZ AL FORMULARIO
        self.setupUi(self)
# VALIDADOR DE MODO DE EDICION
        self.readOnly = True
        self.editmodel = None
#ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana)
        self.categoriesview.headers = ["Descripcion", "Precio", "Unidades","Existencia","","",""]

# Crear el modelo para cargar catalogo de clientes
        self.clientesModel = QSqlQueryModel()
# Crear lista de autocompletado para el combo de clientes
        self.clienteCompleter = QCompleter()     
# Modelo que carga el catalogo de productos
        self.existenciaModel = QSqlQueryModel()

# Establecer todos los controles en modo de edicion
        self.setControls( False )
# Crear la conexion a la base de datos
        self.database = QSqlDatabase.database()

        
        
        self.vistaprevia = False
        
# Cargar los modelos del modo de edicion
        self.updateEditModels()
        self.parent = self.parent()
        

    def newDocument( self ):
        """
        activar todos los controles, llenar los modelos necesarios, 
        crear el modelo FacturaModel, aniadir una linea a la tabla
        """
        self.readOnly = False

        if not self.updateEditModels():
            return

        self.status = False
        self.dtPicker.setDate( self.parentWindow.datosSesion.fecha )

    def updateEditModels( self ):
        """
        Este metodo actualiza los modelos usados en el modo edición
        """
        resultado = False
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo abrir la conexión "\
                                       + "con la base de datos" )
            
            self.clientesModel.setQuery( """
                        SELECT idpersona , nombre AS cliente 
                        FROM personas
                        WHERE escliente = 1
                    """)            
            self.cbcliente.setModel( self.clientesModel )
            
            self.cbcliente.setModelColumn( 1 )
            self.clienteCompleter.setCaseSensitivity( Qt.CaseInsensitive )
            self.clienteCompleter.setModel( self.clientesModel )
            self.clienteCompleter.setCompletionColumn( 1 )
            self.cbcliente.setCompleter( self.clienteCompleter )
            


            self.editmodel = FacturaModel( )

                #           Cargar el numero de la factura actual
            query = QSqlQuery( """
                        SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d;
                    """ % constantes.IDFACTURA )
            if not query.exec_():
                raise Exception( "No se pudo obtener el numero de la factura" )
            query.first()
            
            if query.size()==0:
                n =1
            else:

                n = str(int(query.value(0)) + 1)
                self.editmodel.printedDocumentNumber = str(int(query.value(0)) + 1)

            self.lblnumero.setText(n)


#            if self.clientesModel.rowCount() == 0:
#                raise UserWarning( "No existen clientes en la"\
#                                          + " base de datos" )
#                return
            
            self.clienteCompleter.setModel(self.clientesModel)
            
            self.cbcliente.setModel(self.clientesModel)
            self.cbcliente.setCompleter(self.clienteCompleter)

#        #Crear el delegado con los articulo y verificar si existen articulos
            self.existenciaModel.setQuery( QSqlQuery( """
            SELECT
                categoria,
                descripcion,
                precio,
                unidadesxcaja,
                -- cajas,
                100 as cajas,
                idprecioproducto
            FROM vw_articulos
             -- WHERE existencia >0
                    """ ) )
            self.categoriesview.update("""
            SELECT
                categoria,
                descripcion,
                precio,
                unidadesxcaja,
                -- cajas,
                100 as cajas,
                idprecioproducto
            FROM vw_articulos
            WHERE idprecioproducto IS NOT NULL
             -- WHERE existencia >0
                    """)
            
            self.categoriesview.expandAll()
            self.categoriesview.setColumnHidden(3,True)
            self.categoriesview.setColumnHidden(4,True)
            
            self.categoriesview.setColumnWidth(0,150)
            self.categoriesview.setColumnWidth(1,60)
            self.categoriesview.setColumnWidth(2,20)
            
            
            
            self.proxyexistenciaModel = SingleSelectionModel()
            self.proxyexistenciaModel.setSourceModel( self.existenciaModel )
#            self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX )

            if self.proxyexistenciaModel.rowCount() == 0:
                raise UserWarning( "No hay articulos en bodega" )

            delegate = FacturaDelegate( self.proxyexistenciaModel )


            self.tabledetails.setItemDelegate( delegate )







            self.tabledetails.setModel( self.editmodel )
            self.tabledetails.setColumnHidden(0,True)
#            self.editmodel.insertRow(1)
            self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )

            self.txtobservaciones.setPlainText( "" )
            self.dtPicker.setDate(QDate.currentDate().addDays(1))
            self.editmodel.fecha = QDate.currentDate().addDays(1)
            self.cbcliente.setCurrentIndex( -1 )
            resultado = True
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        finally:
            if self.database.isOpen():
                self.database.close()
        return resultado

    def addActionsToToolBar( self ):
        self.actionRefresh = self.createAction( text = "Actualizar",
                                icon = QIcon.fromTheme( 'view-refresh', QIcon( ":/icons/res/view-refresh.png" ) ),
                                 slot = self.refresh,
                                 shortcut = Qt.Key_F5 )

        self.toolBar.addActions( [
            self.actionNew,
            self.actionRefresh,
            self.actionPreview,
            self.actionPrint,
            self.actionSave,
            self.actionCancel,
        ] )
        self.toolBar.addSeparator()
        self.toolBar.addActions( [
            self.actionGoFirst,
            self.actionGoPrevious,
            self.actionGoLast,
            self.actionGoNext,
            self.actionGoLast
        ] )

    def refresh( self ):
        """
        Actualizar los modelos de edición
        """
        if not self.status:
            if QMessageBox.question( self, qApp.organizationName(),
                                      u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No:
                return
            self.updateEditModels()
        else:
            if self.updateModels():
                QMessageBox.information( None, "Factura",
                                     u"Los datos fueron actualizados con éxito" )


    def printDocument1(self):
        html = u""

        date = QDate.currentDate().toString(self.DATE_FORMAT)
        
        address = Qt.escape("Bario francisco mesa").replace(",","<br>")
        contact = Qt.escape("Luis Mejia")
        balance = 5000
        html += ("<p align=right><img src=':/logo.png'></p>"
                 "<p> align = right>Greasy hands ltd."
                 "<br>New Lombard Street"
                 "<br>London<br>WC13 4PX<br>%s</p>"
                 "<p>%s</p><p>Dear %s, </p>"
                 "<p>The balance of your account is %s.")% (
                   date, address, contact, QString("$ %L1").arg(float(balance),0,"f",2))
                 
        if balance <0 :
            html += ("<p><font color =red><b> Please remit the amount owing immediately.</b></font>")
        else:
            html += "We are delighted to have done business with you."
        
        html += ("</p><p>&nbsp;</p><p>"
                "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>")
        transactions = [
                        (QDate.currentDate(),500),
                        (QDate.currentDate(),500),
                        (QDate.currentDate(),-500),
                        (QDate.currentDate(),500)
                        ]
        for date, amount in transactions:
            color, status = "black", "Credit"
            if amount <0:
                color, status = "red", "Debid"
            
            html += ("<tr>"
                        "<td align= right>%s</td>"
                        "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>" % (
                        date.toString(self.DATE_FORMAT), status,color, QString("$ %L1").arg(float(abs(amount)), 0, "f",2)))
            
        html += ("</table></p><p style='page-break-after=always;'>"
                 "We hope to continue doing business with you</p>")
                 
        
        pdialog = QPrintDialog() 
        if pdialog.exec_() == QDialog.Accepted:
            printer = pdialog.printer()
            document = QTextDocument()
            document.setHtml(html)
            document.print_(printer)

    def printDocument2(self):
        dialog = QPrintDialog()
        if not dialog.exec_():
            return
        self.printer = dialog.printer()
        headFormat = QTextBlockFormat()
        headFormat.setAlignment(Qt.AlignLeft)
        headFormat.setTextIndent(
            self.printer.pageRect().width()-216)
        bodyFormat = QTextBlockFormat()
        bodyFormat.setAlignment(Qt.AlignJustify)
        lastParaBodyFormat = QTextBlockFormat(bodyFormat)
        lastParaBodyFormat.setPageBreakPolicy(QTextFormat.PageBreak_AlwaysAfter)
        rightBodyFormat = QTextBlockFormat()
        rightBodyFormat.setAlignment(Qt.AlignRight)
        headCharFormat = QTextCharFormat()
        headCharFormat.setFont(QFont("Helvetica",10))
        bodyCharFormat = QTextCharFormat()
        bodyCharFormat.setFont(QFont("Times",11))
        redBodyCharFormat = QTextCharFormat(bodyCharFormat)
        redBodyCharFormat.setForeground(Qt.red)
        tableFormat = QTextTableFormat()
        tableFormat.setBorder(1)
        tableFormat.setCellPadding(2)
        
        document = QTextDocument()
        cursor = QTextCursor(document)
        mainFrame = cursor.currentFrame()
        page = 1
        
        cursor.insertBlock(headFormat, headCharFormat)
        
        for text in ("Greasy Hands Ltd.", "New Lombard Street","London" , "WC13", QDate.currentDate().toString(self.DATE_FORMAT)):
            cursor.insertBlock(headFormat,headCharFormat)
            cursor.insertText(text)
        
        cursor.insertBlock(bodyFormat,bodyCharFormat)
        cursor.insertText("Barrio Francisco Meza")
        
        
        cursor.insertBlock(bodyFormat)
        cursor.insertBlock(bodyFormat,bodyCharFormat)
        cursor.insertText("Dear Lyuis")
        cursor.insertBlock(bodyFormat)
        cursor.insertBlock(bodyFormat,bodyCharFormat)
        cursor.insertText(QString("The balance of your account is $ %L1.").arg(float(500.987),0,"f",2))
        
        cursor.insertBlock(bodyFormat,redBodyCharFormat)
        cursor.insertText("Please remit the amount")
        
        cursor.insertBlock(bodyFormat,bodyCharFormat)
        cursor.insertText("Transaction")

        transactions = [
                        (QDate.currentDate(),500),
                        (QDate.currentDate(),500),
                        (QDate.currentDate(),-500),
                        (QDate.currentDate(),500)
                        ]
        
        
        table = cursor.insertTable(len(transactions), 3, tableFormat)
        
        row = 0
        for date, amount in transactions:
            cellCursor = table.cellAt(row,0).firstCursorPosition()
            cellCursor.setBlockFormat(rightBodyFormat)
            cellCursor.insertText(date.toString(self.DATE_FORMAT),bodyCharFormat)
            
            cellCursor = table.cellAt(row,1).firstCursorPosition()
            cellCursor.insertText("Credit",bodyCharFormat)
            
            cellCursor = table.cellAt(row,2).firstCursorPosition()
            cellCursor.setBlockFormat(rightBodyFormat)
            
            cellCursor.insertText(QString("The balance of your account is $ %L1.").arg(float(amount),0,"f",2),redBodyCharFormat)
            
            row += 1
            
        cursor.setPosition(mainFrame.lastPosition())
        cursor.insertBlock(bodyFormat,bodyCharFormat)
        cursor.insertText("We hope")
        document.print_(self.printer)



    def printDocument(self):
        dialog = QPrintDialog()
        if not dialog.exec_():
            return
        self.printer = dialog.printer()    
        self.imprimir(self.printer)
        self.document.load(self.editmodel)
        

    def preview(self):    
        self.vistaprevia = True     
        preview = frmImpresion(self)
        preview.exec_()
        
           
    def save( self ):
        """
        Guardar el documento actual
        @rtype: bool
        """
        result = False
        try:
            if not self.valid:
                return False

            if QMessageBox.question( self, qApp.organizationName(),
                                     u"¿Esta seguro que desea guardar la factura?",
                                     QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:

                if not self.database.isOpen():
                    if not self.database.open():
                        raise UserWarning( u"No se pudo conectar con la base de datos" )

                self.editmodel.observaciones = self.txtobservaciones.toPlainText()
                if not self.editmodel.save():
                    raise UserWarning( "No se ha podido guardar la factura" )

                QMessageBox.information( None,
                     qApp.organizationName() ,
                     u"""El documento se ha guardado con éxito""" )

                
                self.readOnly = True
                
                self.updateModels()

#                self.navigate( 'last' )
#                self.status = True
                result = True
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                 u"Hubo un error al guardar la factura" )
        finally:
            if self.database.isOpen():
                self.database.close()
        return result

#    @pyqtSlot(QModelIndex)    
#    def on_categoriesview_doubleClicked(self,index):
    @pyqtSlot(QModelIndex)    
    def on_categoriesview_activated(self,index):
        articulo = self.categoriesview.model().asRecord(index)
        if len(articulo)>0:
            nuevo = True
            
            for i, line in enumerate(self.editmodel.lines):
                if line.itemId == articulo [5]:
                    nuevo = False
                    fila = i
                    line = self.editmodel.lines[self.editmodel.rowCount()-1]
                
            if nuevo:       
                fila = self.editmodel.rowCount()
                self.editmodel.insertRow(fila)
                self.parent.saveAct.setEnabled(True)
                linea = self.editmodel.lines[fila]        
                linea.itemDescription = articulo[0] + " " + articulo [1]
                linea.itemPrice = Decimal(articulo[2])
                linea.itemId = articulo[5]
                
                linea.quantityperbox = int(articulo[3])
            
            
            self.editmodel.lines[fila].quantity += 1
            self.editmodel.lines[fila].existencia  = int(articulo[4]) - self.editmodel.lines[fila].quantity 
            indice =self.editmodel.index( fila,2)
            self.editmodel.dataChanged.emit( indice, indice )
            indice =self.editmodel.index( fila,3)
            self.editmodel.dataChanged.emit( indice, indice )
            indice =self.editmodel.index( fila,5)
            self.editmodel.dataChanged.emit( indice, indice )
    
      
    @pyqtSlot()
    def on_btneditar_clicked( self ):
        articulo = dlgArticulo(self)
        articulo.exec_()
        self.updateEditModels()

    @pyqtSlot( int )   
    def on_cbcliente_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        if self.editmodel is not None:
            numero = self.clientesModel.record( index ).value( "idpersona" )
            self.editmodel.clienteId = int(numero) if numero is not None else 0

    @pyqtSlot( unicode )   
    def on_cbcliente_editTextChanged( self, text ):
        """
        asignar proveedor al objeto self.editmodel
        """
        if self.editmodel is not None:
            self.editmodel.cliente =str( text)


    @pyqtSlot( int )
    
    def on_cbvendedor_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.vendedorId = self.vendedoresModel.record( index ).value( "idpersona" ).toInt()[0]


    @pyqtSlot( QDate)
    def on_dtPicker_dateChanged( self, date ):
        if self.editmodel is not None:
            self.editmodel.fecha = date

    @pyqtSlot( bool )
    def on_rbcontado_toggled( self, on ):
        """
        Asignar las observaciones al objeto editmodel
        """
        self.editmodel.escontado = 1 if on else 0

    def on_txtSearch_textChanged( self, text ):
        """
        Cambiar el filtro de busqueda
        """
        self.filtermodel.setFilterRegExp( text )

    def setControls( self, status ):
        """
        @param status: false = editando        true = navegando
        """
#        self.actionPrint.setVisible( status )
        self.readOnly = status
        self.txtobservaciones.setReadOnly( status )
#        self.actionPreview.setVisible( status )
#        self.actionAnular.setVisible( status )
#        self.toolBar.setVisible(status)

#        self.lblnfac.setText( self.editmodel.printedDocumentNumber )
        self.swcliente.setCurrentIndex( 0 )
        self.lbltotal.setText( "C$ 0.00" )
        self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers )
#        self.lblanulado.setHidden( True )



        self.tabledetails.horizontalHeader().setStretchLastSection(True)

        self.tabledetails.setColumnHidden( IDARTICULO, True )
        self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )



    def updateLabels( self ):
        self.lbltotal.setText( moneyfmt( self.editmodel.total, 2, "C$ " ) )
        
        

    @property
    def valid( self ):
        """
        Un documento es valido cuando 
        self.printedDocumentNumber != ""
        self.providerId !=0
        self.validLines >0
        self.ivaId !=0
        self.uid != 0
        self.warehouseId != 0
        """
        if int( self.editmodel.clienteId) == 0 and self.editmodel.cliente == "":
            QMessageBox.warning( self, qApp.organizationName(),
                                  "Por favor elija el cliente" )
            self.cbcliente.setFocus()
            
        elif self.editmodel.rowCount() == 0:
            QMessageBox.warning( self, qApp.organizationName(),
                              "Por favor agregue algun articulo a la factura" )
        else:
            return True
        return False


                
    def imprimir(self,printer):
        
        leftMargin = 72
        widthCol = 100

        
        arialFont = QFont("Helvetica",16,3)
        
        fuente =QFontMetrics(arialFont)
        arialLineHeight = fuente.height()
        
        fondo = QPixmap(":/images/res/fondo.png")     
        painter = QPainter(printer)
        pageRect = printer.pageRect()
        page = 1
        
        painter.save()
        if self.vistaprevia:
            painter.drawPixmap(0, 0, 530, 830, fondo)
        
        painter.setFont(arialFont)
        
        y = 180
        x = 35
        painter.drawText(x,y,self.editmodel.fecha.toString("dd   MM   yy"))
        
        y = 210
        x = 85
        
        painter.drawText(x,y, self.editmodel.cliente)
        
        painter.setFont(arialFont)

        
        cajasFont = QFont("Helvetica",10,2)
        x = -5
        y = 295
         
        painter.setFont(cajasFont)
        painter.drawText(x,y - arialLineHeight - 1,"Cajas")
        
        
        for row in self.editmodel.lines:
            painter.setFont(cajasFont)
            x = 2
            painter.drawText(x,y,row.cantidad())

            painter.setFont(arialFont)
            total = moneyfmt(row.total,2,"")
            x = 470 - fuente.width(total)
            painter.drawText(x,y,total)
            
            x =310
            painter.drawText(x,y,moneyfmt(row.itemPrice,2,""))
            


            x = 30                                
            painter.drawText(x,y,row.unidades())
            
            
            x = 80
            painter.drawText(x,y,row.itemDescription)            

            
            
            y+= arialLineHeight
            
        
        total = moneyfmt(self.editmodel.total,2,"")
        y= 690
        x = 470 - fuente.width(total)   
        painter.drawText(x,y,total)
        
        
        painter.setPen(Qt.black)
#        printer.newPage()
        painter.restore()
Ejemplo n.º 8
0
class ChooseMTModelDialog(QDialog, Ui_Dialog):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None, datamodel=None):
        """
        Constructor
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.model = QSqlQueryModel()
        self.selTableView.setModel(self.model)
        self.database = datamodel.getQSqlDatabase()
        self.updateModel()
        self.selTableView.hideColumn(0)
        self.selTableView.hideColumn(5)
        self.selTableView.hideColumn(6)
        # Change status and keep the column.
        QObject.connect(datamodel, SIGNAL("modelInstalled()"),
                        self.on_datamodel_modelInstalled)

    def updateModel(self):
        self.model.setQuery(
            'SELECT ID, name, srclang, trglang, status, path, mosesini '
            'FROM models '
            'WHERE status = "READY" AND deleted != "True"', self.database)

    def on_datamodel_recordUpdated(self, bRecord):
        """Deal with the selection changed problem."""
        try:
            if bRecord:
                current = self.selTableView.currentIndex()
                if current and current.row() != -1:
                    self.curSelection = current.row()
                else:
                    self.curSelection = None
            else:
                if self.curSelection is not None:
                    self.selTableView.selectRow(self.curSelection)
        except Exception as e:
            print >> sys.stderr, str(e)

    def on_datamodel_modelInstalled(self):
        self.updateModel()

    @pyqtSignature("")
    def on_buttonBox_accepted(self):
        """
        Slot documentation goes here.
        """
        current = self.selTableView.currentIndex()
        if not current:
            doAlert("Please choose a model to start.")
            return
        record = self.model.record(current.row())
        self.ID = record.value("ID").toString()
        self.modelName = record.value("name").toString()
        self.srcLang = record.value('srclang').toString()
        self.trgLang = record.value('trglang').toString()
        self.path = record.value("path").toString()
        self.mosesini = record.value("mosesini").toString()
        self.accept()
Ejemplo n.º 9
0
    def createHtmlReport(self):
        homepath = expanduser('~')
        filePath = self.chooseSaveFile(os.path.join(homepath, 'report.html'), 'html')
        if not filePath:
            return
        editor = QtGui.QTextDocument()
        cursor = QtGui.QTextCursor(editor)
        cursor.beginEditBlock()
        cursor.insertHtml(u"<B>ПРИМЕР ОТЧЕТА №1 от %s</B><BR>" % datetime.datetime.now().strftime('%Y-%m-%d'))
        cursor.insertHtml(u"Дополнительная строка  %s от %s" % ('_' * 3, '_' * 10))

        clientQuery = QSqlQueryModel()
        clientQuery.setQuery(
            "SELECT Surname, Name, Midname, birthdate, sex, snils FROM Client where id=%s" % self.clientId)
        tableFormat = QtGui.QTextTableFormat()
        constraints = [QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 14),
                       QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 14)]

        tableFormat.setBorder(0)
        tableFormat.setCellPadding(2)
        tableFormat.setCellSpacing(0)
        tableFormat.setColumnWidthConstraints(constraints)
        tableFormat.setHeaderRowCount(10)

        table = cursor.insertTable(4, 2, tableFormat)
        paramMap = {}
        paramMap[0] = [u'ФИО пациента:', clientQuery.record(0).value("Surname").toString() + " " +
                       clientQuery.record(0).value("Name").toString() + " " +
                       clientQuery.record(0).value("Midname").toString()]
        paramMap[1] = [u'Дата рождения:', unicode(clientQuery.record(0).value('birthdate').toString())]
        paramMap[2] = [u'СНИЛС', unicode(clientQuery.record(0).value('snils').toString())]
        paramMap[3] = [u'Пол', u'М' if 1 == clientQuery.record(0).value('sex').toInt() else u'Ж']

        for param in paramMap:
            for i in xrange(2):
                cell = table.cellAt(param, i)
                cellCursor = cell.firstCursorPosition()
                cellCursor.insertText(paramMap[param][i])
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertHtml(u"<B>Информация об оказанных услугах</B><BR><BR>")

        cursor.movePosition(QtGui.QTextCursor.End)
        constraints = [QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 5),
                       QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 10),
                       QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 25)]
        tableFormat.setBorder(1)
        tableFormat.setCellPadding(2)
        tableFormat.setCellSpacing(0)
        tableFormat.setColumnWidthConstraints(constraints)
        tableFormat.setHeaderRowCount(1)

        clientQuery.setQuery('''SELECT distinct s.*
                                FROM Client c
                                INNER join cure cr on cr.Client_id = c.id
                                INNER join services s on s.id = cr.services_id
                                where c.id = %d''' % self.clientId)

        table = cursor.insertTable(clientQuery.rowCount() + 1, 3, tableFormat)
        values = [u'№ п/п', u'Код', u'Наименование услуги']
        for i in xrange(3):
            cell = table.cellAt(0, i)
            cellCursor = cell.firstCursorPosition()
            cellCursor.insertText(values[i])
        for i in xrange(clientQuery.rowCount()):
            for j in xrange(clientQuery.columnCount()):
                cell = table.cellAt(i + 1, j)
                cellCursor = cell.firstCursorPosition()
                cellCursor.insertText(unicode(clientQuery.record(i).value(j).toString()))
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertHtml(u'Дата печати: <B>%s</B><BR>' % datetime.datetime.now().strftime('%Y-%m-%d'))
        cursor.endEditBlock()

        writer = QtGui.QTextDocumentWriter()
        writer.setFileName(filePath)
        writer.setFormat("HTML")
        writer.write(editor)
Ejemplo n.º 10
0
    def loadtree(self, geom, epsg, pid, profilename, buffervalue):

        epsg = self.xuni(epsg)
        pid = self.xuni(pid)
        profilename = self.xuni(profilename)

        # Create profile model
        if self.parent.dbmeta.isOpen():

            # Create model for treeview
            model = QtGui.QStandardItemModel()
            model.setHorizontalHeaderLabels(['Identification'])

            # Find treeview widget from dialog
            view = self.twResult
            view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
            view.clicked.connect(self.on_viewClicked)

            # Set model and looks for treeview
            view.setModel(model)
            view.setUniformRowHeights(True)
            view.setAlternatingRowColors(True)
            view.header().setStretchLastSection(True)
            view.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)

            # Fetch profile data from database
            profilemodel = QSqlQueryModel()
            profilemodel.setQuery(
                'select * from "' + self.parent.config['db_schema'] +
                '"."profiles_layers_view" where pid = ' + str(pid),
                self.parent.dbmeta)

            # Create root item
            profile = QtGui.QStandardItem(
                tr(u'{} ({} layers)').format(profilename,
                                             profilemodel.rowCount()))

            # Get profile link (if it can be retrieved (no of layers > 0)
            if profilemodel.rowCount() > 0:
                profile.setData(
                    u'p|' +
                    self.xuni(profilemodel.record(0).value('profile_link')) +
                    u'|||')
            else:
                profile.setData(u'p||||')

            # Create root item
            model.appendRow(profile)

            # rowcounter layers with non-zero conflicts
            nextRow = 0

            # Iterate through layers in selected profile.....
            for i in range(profilemodel.rowCount()):

                # Fetch record nr. i
                r = profilemodel.record(i)

                # Rowcount default (-1 --> db not open)
                rc = -1

                # Open or reconnect database for layer
                dbl = self.parent.connectDatabase('c' + str(r.value('cid')),
                                                  r.value('servertypename'),
                                                  r.value('host'),
                                                  r.value('port'),
                                                  r.value('username'),
                                                  r.value('password'),
                                                  r.value('database'),
                                                  r.value('serverconnection'))
                if not dbl is None:

                    # Create wkt string for layer query
                    # (it has to be converted for each layer - they might have different projections)
                    wkt = self.parent.cnvobj2wkt(geom, epsg, r.value('epsg'))

                    # Fetch layerdata from database
                    layermodel = QSqlQueryModel()

                    # Generate SQL statement
                    sel1 = r.value('sql_detail').format(
                        r.value('profilename'), r.value('layername'),
                        r.value('compoundid'), r.value('linkid'),
                        r.value('geomid'), r.value('schemaname'),
                        r.value('tablename'))
                    sel2 = r.value('sql_filter').format(
                        wkt, r.value('epsg'), buffervalue, r.value('geomid'))
                    sel = sel1 + u' where ' + sel2

                    # Execute SQL and create layermodel content
                    layermodel.setQuery(sel, dbl)
                    rc = layermodel.rowCount()

                    # Create stub QStandardItem for layer
                    lName = QtGui.QStandardItem(
                        tr(u'{} ({} overlaps)').format(r.value('layername'),
                                                       rc))
                    lName.setData(u'l|' + self.xuni(r.value('layerlink')) +
                                  u'|' + self.xuni(r.value('qlr_file')) +
                                  u'||')

                    for j in range(rc):

                        # Fetch record nr. j
                        q = layermodel.record(j)

                        # Append data to lName item
                        li = QtGui.QStandardItem(q.value('layerid'))
                        li.setData(u'i|' + self.xuni(q.value('link')) + '|' +
                                   self.xuni(r.value('qlr_file')) + '|' +
                                   self.xuni(q.value('wkt_geom')) + '|' +
                                   self.xuni(r.value('epsg')))
                        lName.appendRow(li)

                #Append layerinfo to profile item
                if rc > 0:
                    lName.setBackground(QtGui.QColor(255, 230, 230))
                    lName.sortChildren(0)
                    profile.insertRow(nextRow, lName)
                    nextRow = nextRow + 1
                elif rc == 0:
                    profile.appendRow(lName)
                else:
                    pass  # db not found

        view.expandToDepth(0)
Ejemplo n.º 11
0
class FrmEntradaCompra( Ui_frmEntradaCompra, Base ):
    """
    Implementacion de la interfaz grafica para entrada compra
    """
    web = "entradaslocales.php?doc="
    def __init__( self, parent = None ):
        """
        Constructor
        """
        super( FrmEntradaCompra, self ).__init__( parent )





        self.status = True


#        El modelo principal
        self.navmodel = QSqlQueryModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = RONavigationModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
#        Este es el modelo con los datos de la con los detalles
        self.detailsmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )
        self.detailsproxymodel.setSourceModel( self.detailsmodel )

        self.providersModel = QSqlQueryModel()

        #inicializando el documento
        self.editmodel = None



        #general events
        self.rbCash.clicked[bool].connect( self.__update_pay )
        self.rbCheck.clicked[bool].connect( self.__update_pay )
        self.rbCredit.clicked[bool].connect( self.__update_pay )

        self.tabledetails.setOrder( 1, 4 )
        self.delegate = EntradaCompraDelegate()

        QTimer.singleShot( 0, self.loadModels )



    def __update_pay( self, _checked ):
        if not self.editmodel is None:
            if self.sender() in ( self.rbCash, self.rbCheck ):
                self.editmodel.paytipe = 1
            elif self.sender() == self.rbCredit:
                self.editmodel.paytipe = 0

            self.editmodel.isCheck = self.sender() == self.rbCheck

    def updateModels( self ):
        """
        Recargar todos los modelos
        """
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( "No se pudo conectar con la base de"\
                                    + " datos para obtener los documentos" )


#        El modelo principal

            self.navmodel.setQuery( """
            SELECT  
                d.iddocumento,
                d.ndocimpreso AS 'Numero de Entrada',
                d.fechacreacion AS 'Fecha',
                p.nombre as Proveedor,
                d.observacion,
                (@subtotalc:=( ( d.total / (1 + (ca.valorcosto / 100)  ) ) )  * tc.tasa  ) AS 'Subtotal C$',
                ( @subtotalc * (  (ca.valorcosto / 100) ) )  AS 'IVA',
                d.total * tc.tasa AS 'Total C$',
                d.total AS 'Total US$',
                escontado as tipopago
            FROM documentos d  
            JOIN personasxdocumento pxd ON pxd.iddocumento = d.iddocumento 
            JOIN personas p ON pxd.idpersona = p.idpersona AND p.tipopersona = %d
            JOIN articulosxdocumento axd ON axd.iddocumento = d.iddocumento
            JOIN costosxdocumento cxd ON cxd.iddocumento = d.iddocumento
            JOIN costosagregados ca ON cxd.idcostoagregado = ca.idcostoagregado
            JOIN tiposcambio tc ON tc.idtc = d.idtipocambio
            WHERE d.idtipodoc = %d
            GROUP BY d.iddocumento
            """ % ( constantes.PROVEEDOR, constantes.IDENTRADALOCAL ) )
    #        El modelo que filtra a self.navmodel
            self.navproxymodel = RONavigationModel( self )
            self.navproxymodel.setSourceModel( self.navmodel )
            self.navproxymodel.setFilterKeyColumn( -1 )
            self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )
    #        Este es el modelo con los datos de la tabla para navegar
            self.detailsmodel = QSqlQueryModel( self )
            self.detailsmodel.setQuery( u"""
                 SELECT 
                    a.idarticulo as id,  
                    CONCAT(m.nombre,' ' , c.nombre, ' ' , subc.nombre) as 'Descripción',  
                    axd.unidades as 'Cantidad',   
                    CONCAT('C$',FORMAT((axd.costounit * tc.tasa),4)) as 'Precio C$',
                    CONCAT('US$', axd.costounit) as 'Precio US$',  
                    CONCAT('C$',FORMAT(((axd.unidades * axd.costounit) * tc.tasa),4)) as 'Total C$',
                    CONCAT('US$',FORMAT((axd.unidades * axd.costounit),4)) as 'Total US$',
                    d.iddocumento
                FROM documentos d  
                JOIN articulosxdocumento axd ON axd.iddocumento=d.iddocumento  
                JOIN articulos a ON a.idarticulo = axd.idarticulo  
                JOIN marcas m ON m.idmarca = a.idmarca  
                JOIN categorias subc ON a.idcategoria = subc.idcategoria  
                JOIN categorias c ON subc.padre = c. idcategoria  
                JOIN tiposcambio tc ON tc.idtc = d.idtipocambio
                WHERE d.idtipodoc = %d
            """ % constantes.IDENTRADALOCAL )
    #        Este es el filtro del modelo anterior
            self.detailsproxymodel = QSortFilterProxyModel( self )
            self.detailsproxymodel.setSourceModel( self.detailsmodel )


    #        Este objeto mapea una fila del modelo self.navproxymodel a 
    #los controles

            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.txtDocumentNumber, NDOCIMPRESO )
            self.mapper.addMapping( self.txtObservations, OBSERVACION )
            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.txtProvider, PROVEEDOR, "text" )
            self.mapper.addMapping( self.lblSubtotal, SUBTOTALC, "text" )
            self.mapper.addMapping( self.lblIVA, IVAC, "text" )
            self.mapper.addMapping( self.lblTotal, TOTALC, "text" )
            self.mapper.addMapping( self.lblTotalD, TOTALD, "text" )

    #        asignar los modelos a sus tablas
            self.tablenavigation.setModel( self.navproxymodel )
            self.tabledetails.setModel( self.detailsproxymodel )



        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                  unicode( inst ) )
            logging.error( unicode( inst ) )
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                          "No se pudo cargar la lista de entradas locales" )
            logging.critical( unicode( inst ) )
        finally:
            if self.database.isOpen():
                self.database.close()

    def updateEditModels( self ):
#            Rellenar el combobox de los proveedores
        self.providersModel.setQuery( """
            SELECT idpersona , nombre AS proveedor 
            FROM personas
            WHERE tipopersona = 2
        """ )
        if not self.providersModel.rowCount( QModelIndex() ) > 0:
            raise UserWarning( "No existen proveedores en la base de datos" )
        self.cbProvider.setModel( self.providersModel )
        self.cbProvider.setModelColumn( 1 )

        completer = QCompleter()
        completer.setCaseSensitivity( Qt.CaseInsensitive )
        completer.setModel( self.providersModel )
        completer.setCompletionColumn( 1 )

        self.editmodel.providerId = self.providersModel.record( 
                                        self.cbProvider.currentIndex()
                                        ).value( "idpersona" ).toInt()[0]
        query = QSqlQuery( """
        SELECT idarticulo, Descripcion as descripcion 
        FROM vw_articulosdescritos
        """ )
        if not query.size() > 0:
            raise UserWarning( "No existen productos en la base de datos" )
        prods = SingleSelectionModel()
        query.exec_()
        while query.next():
            prods.items.append( [
                query.value( 0 ).toInt()[0],
                query.value( 1 ).toString()
                       ] )

        prods.headers = ["idarticulo", "Articulo"]
        self.delegate.prods = prods

    @if_edit_model
    def updateLabels( self, index1 = None, index2 = None ):
        self.lblSubtotal.setText( 
                          moneyfmt( self.editmodel.subtotalC, 4, "C$" ) )

        self.lblIVA.setText( moneyfmt( self.editmodel.IVAC, 4, "C$" ) )

        self.lblTotal.setText( moneyfmt( self.editmodel.totalC, 4, "C$" ) )

        self.lblTotalD.setText( 
                            moneyfmt( self.editmodel.totalD, 4, "US$" ) )
    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex()
                                      ).value( "iddocumento" ).toString()



    def newDocument( self ):
        """
        activar todos los controles, llenar los modelos necesarios,
        crear el modelo EntradaCompraModel, aniadir una linea a la tabla
        """
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo establecer la conexión "\
                                       + "con la base de datos" )

            self.editmodel = EntradaCompraModel()
            self.editmodel.uid = self.user.uid
            self.tabledetails.setModel( self.editmodel )

            self.tabledetails.setItemDelegate( self.delegate )

            query = QSqlQuery( """
            SELECT idcostoagregado, valorcosto 
            FROM costosagregados c 
            WHERE idtipocosto = %d AND activo = 1 
            LIMIT 1
            """ % constantes.IVA )
            if not query.exec_():
                raise UserWarning( "No se pudo obtener el valor del IVA "\
                                   + "para iniciar la entrada compra" )
            if not query.size() == 1:
                raise UserWarning( "No se pudo obtener el valor del IVA "\
                                   + "para iniciar la entrada compra" )
            query.first()
            self.editmodel.idIVA = query.value( 0 ).toInt()[0]
            self.editmodel.rateIVA = Decimal( query.value( 1 ).toString() )


            self.updateEditModels()


            self.rbCash.click()

            self.addLine()
            self.dtPicker.setDateTime( QDateTime.currentDateTime() )
            self.editmodel.providerId = self.providersModel.record( 
                                           self.cbProvider.currentIndex()
                                            ).value( "idpersona" ).toInt()[0]

            self.editmodel.dataChanged[QModelIndex,
                                       QModelIndex].connect( self.updateLabels )
            self.tabledetails.setColumnWidth( DESCRIPCION, 250 )
            self.status = False
        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                   unicode( inst ) )
            logging.error( unicode( inst ) )
#            self.status = True
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                              "No se pudo iniciar una nueva entrada compra" )
            logging.error( unicode( inst ) )
#            self.status = True

        if self.database.isOpen():
            self.database.close()


    def cancel( self ):
        """
        Aca se cancela la edicion del documento
        """
        if QMessageBox.question( self, qApp.organizationName(),
                              u"¿Desea realmente cancelar?",
                               QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
            self.editmodel = None

            self.tablenavigation.setModel( self.navproxymodel )
            self.tabledetails.setModel( self.detailsproxymodel )
            self.tabledetails.removeAction( self.actionDeleteRow )

            self.status = True


    def updateDetailFilter( self, index ):
        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        record = self.navmodel.record( index )
        self.detailsproxymodel.setFilterRegExp( "^%d$" %
                                     record.value( IDDOCUMENTO ).toInt()[0] )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )

        paytype = record.value( TIPOPAGO ).toInt()[0]
        if paytype == 0:
            self.rbCredit.setChecked( True )
        elif paytype == 1:
            self.rbCash.setChecked( True )




    def setControls( self, status ):
        """
        @param status: false = editando        true = navegando
        """
        self.txtDocumentNumber.setReadOnly( status )
        self.actionPrint.setVisible( status )
        self.dtPicker.setReadOnly( status )
        self.txtObservations.setReadOnly( status )

        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )
        self.rbCash.setEnabled( not status )
        self.rbCheck.setEnabled( not status )
        self.rbCredit.setEnabled( not status )

        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionPreview.setVisible( status )


        if status:
            self.navigate( 'last' )
            self.swProvider.setCurrentIndex( 1 )
            self.tabledetails.removeAction( self.actionDeleteRow )
            self.tabledetails.setEditTriggers( 
                                          QAbstractItemView.NoEditTriggers )

            #ocultar columnas en tabledetails
            self.tabledetails.setColumnHidden( IDARTICULO, True )
            self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )
            #ocultar columnas en tablenavigation
            self.tablenavigation.setColumnHidden( TIPOPAGO, True )
            self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
            self.tablenavigation.setColumnHidden( OBSERVACION, True )
            self.tablenavigation.setColumnHidden( SUBTOTALC, True )
            self.tablenavigation.setColumnHidden( IVAC, True )
        else:
            self.tabledetails.addAction( self.actionDeleteRow )
            self.tabWidget.setCurrentIndex( 0 )
            self.txtDocumentNumber.setText( "" )
            self.txtObservations.setPlainText( "" )
            self.swProvider.setCurrentIndex( 0 )

            self.lblSubtotal.setText( "C$0.00" )
            self.lblIVA.setText( "C$0.00" )
            self.lblTotal.setText( "C$0.00" )
            self.tabledetails.setEditTriggers( 
                                          QAbstractItemView.AllEditTriggers )
            self.tabledetails.setColumnHidden( IDARTICULO, True )


    @pyqtSlot( unicode )
    @if_edit_model
    def on_txtDocumentNumber_textChanged( self, text ):
        """
        Asignar el contenido al objeto documeto
        """
        self.editmodel.printedDocumentNumber = text



    @pyqtSlot( int )
    @if_edit_model
    def on_cbProvider_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.providerId = self.providersModel.record( index
                                            ).value( "idpersona" ).toInt()[0]
Ejemplo n.º 12
0
class FrmCheques(Base, Ui_frmCheques):
    """
    Implementacion de la interfaz grafica para Cheques
    """

    web = "cheques.php?doc="

    def __init__(self, parent):
        """
        Constructor
        """
        super(FrmCheques, self).__init__(parent)

        self.navmodel = QSqlQueryModel(self)
        self.navproxymodel = QSortFilterProxyModel(self)
        self.navproxymodel.setSourceModel(self.navmodel)

        self.accountsModel = QSqlQueryModel()
        self.accountsProxyModel = ROAccountsModel(self)
        self.accountsProxyModel.setSourceModel(self.accountsModel)

        #        El modelo que filtra a self.navmodel
        self.navproxymodel.setFilterKeyColumn(-1)
        self.navproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.editmodel = None

        self.status = True
        # las acciones deberian de estar ocultas

        # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        QTimer.singleShot(0, self.loadModels)

    # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    def updateDetailFilter(self, index):
        record = self.navmodel.record(index)
        self.accountsProxyModel.setFilterKeyColumn(IDDOCUMENTO)
        self.accountsProxyModel.setFilterRegExp(record.value("iddocumento").toString())
        self.tablenavigation.selectRow(self.mapper.currentIndex())
        self.actionAnular.setEnabled(record.value("idestado").toInt()[0] == constantes.CONFIRMADO)

    #        if record.value( "caret.valorcosto" )>Decimal(0.00):
    #            print "tiene retencion"
    #
    def updateModels(self):
        # inicializando el documento
        # El modelo principal
        # FIXME Revisar escape del %
        # TODO:REVISAR BIEN

        self.navmodel.setQuery(
            u"""
        SELECT padre.iddocumento,
            padre.ndocimpreso as 'No. Cheque',
            cb.descripcion as 'Cuenta Bancaria',
            p.nombre as Cliente,
            DATE(padre.fechacreacion) as 'Fecha',
            c.descripcion as 'En concepto de',
            IF (tm.simbolo="C$",CONCAT(tm.simbolo,FORMAT(padre.total*tc.tasa,4)),CONCAT(tm.simbolo,FORMAT(padre.total,4))) as Total,
            
            IF (tm.simbolo="C$",ROUND(padre.total*tc.tasa/ (1+ IF(ca.valorcosto IS NULL,0,ca.valorcosto/100))),ROUND(padre.total/ (1+ IF(ca.valorcosto IS NULL,0,ca.valorcosto/100)))) as subtotal,
            
            IF (tm.simbolo="C$",CONCAT(tm.simbolo,FORMAT(tc.tasa*padre.total-(tc.tasa*padre.total/(1+ IF(ca.valorcosto IS NULL,0,ca.valorcosto/100))),4)),CONCAT(tm.simbolo,FORMAT(padre.total-(padre.total/(1+ IF(ca.valorcosto IS NULL,0,ca.valorcosto/100))),4))) as iva,
                       
            IF(hijo.total IS NULL, CONCAT(tm.simbolo,'0.0000') ,CONCAT(tm.simbolo,hijo.total))   as 'Total Ret C$',
            tc.tasa as TipoCambio,
            caret.valorcosto as 'retencion',
            ed.descripcion AS Estado,
            padre.idestado,
            IF (tm.simbolo="C$",padre.total*tc.tasa,padre.total) as TotalCheque
            FROM documentos padre
            JOIN estadosdocumento ed ON ed.idestado = padre.idestado
            JOIN tiposcambio tc on padre.idtipocambio=tc.idtc
            JOIN personasxdocumento pxd ON padre.iddocumento=pxd.iddocumento
            JOIN personas p ON p.idpersona=pxd.idpersona
            JOIN conceptos c ON  c.idconcepto=padre.idconcepto
            
            LEFT JOIN costosxdocumento cd ON cd.iddocumento=padre.iddocumento
            LEFT JOIN  costosagregados ca ON ca.idcostoagregado=cd.idcostoagregado
            LEFT JOIN docpadrehijos ph ON  padre.iddocumento=ph.idpadre
            LEFT JOIN documentos hijo ON hijo.iddocumento=ph.idhijo
            
            LEFT JOIN costosxdocumento cdret ON cdret.iddocumento=hijo.iddocumento
            LEFT JOIN  costosagregados caret ON caret.idcostoagregado=cdret.idcostoagregado            
            
            JOIN cuentasxdocumento cuentasdoc on cuentasdoc.iddocumento=padre.iddocumento
            JOIN cuentascontables cb ON cb.idcuenta=cuentasdoc.idcuenta
            JOIN cuentasbancarias cbank on cb.idcuenta=cbank.idcuentacontable
            JOIN tiposmoneda tm on tm.idtipomoneda=cbank.idtipomoneda 
            WHERE padre.idtipodoc= %d AND p.tipopersona = %d
            GROUP BY padre.iddocumento
            ORDER BY CAST(IF(padre.ndocimpreso="S/N",0, padre.ndocimpreso )AS SIGNED)
        """
            % (constantes.IDCHEQUE, constantes.PROVEEDOR)
        )
        #        El modelo que filtra a self.navmodel

        self.tablenavigation.resizeColumnsToContents()

        # Este es el modelo para las cuentas

        self.accountsModel.setQuery(
            """
        SELECT
            c.iddocumento, 
            c.idcuenta,
            cc.codigo as Codigo,
            cc.descripcion as Nombre,
            c.monto as Monto
        FROM cuentasxdocumento c 
        JOIN documentos d ON c.iddocumento = d.iddocumento
        JOIN cuentascontables cc ON cc.idcuenta = c.idcuenta
        WHERE d.idtipodoc = %d
        ORDER BY nlinea
        """
            % (constantes.IDCHEQUE)
        )

        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(self.navproxymodel)
        self.mapper.addMapping(self.lblncheque, NCHEQUE, "text")
        self.mapper.addMapping(self.dtPicker, FECHA, "date")
        self.mapper.addMapping(self.lblbeneficiario, NOMBRE, "text")
        self.mapper.addMapping(self.total, TOTAL, "text")
        self.mapper.addMapping(self.lblconcepto, CONCEPTO, "text")
        self.mapper.addMapping(self.retencion, TOTALRET, "text")
        self.mapper.addMapping(self.lbltipocambio, TIPOCAMBIO, "text")
        self.mapper.addMapping(self.subtotal, SUBTOTAL)
        self.mapper.addMapping(self.iva, IVA, "text")
        self.mapper.addMapping(self.lblcuenta, CUENTABANCARIA, "text")
        self.mapper.addMapping(self.lblretencion, TASARETENCION, "text")
        self.tablenavigation.setModel(self.navproxymodel)
        self.tabledetails.setModel(self.accountsProxyModel)

        self.tabledetails.setColumnHidden(IDCUENTA, True)
        self.tabledetails.setColumnHidden(IDDOC, True)
        self.tablenavigation.setColumnHidden(TIPOCAMBIO, True)
        self.tablenavigation.setColumnHidden(SUBTOTAL, True)
        self.tablenavigation.setColumnHidden(IVA, True)
        self.tablenavigation.setColumnHidden(IDDOCUMENTO, True)
        self.tablenavigation.setColumnHidden(CONCEPTO, True)
        self.tablenavigation.setColumnHidden(CONCEPTO, True)
        self.tablenavigation.setColumnHidden(IDESTADO, True)
        self.tablenavigation.setColumnHidden(TOTALCHEQUE, True)

        self.tablenavigation.resizeColumnsToContents()

    def addActionsToToolBar(self):
        self.actionAnular = self.createAction(text="Anular", icon=":/icons/res/edit-delete.png", slot=self.anular)

        self.toolBar.addActions(
            [
                self.actionNew,
                self.actionPreview,
                self.actionPrint,
                self.actionSave,
                self.actionCancel,
                self.actionAnular,
            ]
        )
        self.toolBar.addSeparator()
        self.toolBar.addActions(
            [self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast]
        )

    def setControls(self, status):
        """
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible(status)
        self.dtPicker.setReadOnly(status)
        self.subtotal.setReadOnly(status)
        self.txtobservaciones.setReadOnly(status)

        self.actionGoFirst.setVisible(status)
        self.actionGoPrevious.setVisible(status)
        self.actionGoNext.setVisible(status)
        self.actionGoLast.setVisible(status)
        self.actionAnular.setVisible(status)

        self.actionSave.setVisible(not status)
        self.actionCancel.setVisible(not status)
        self.actionNew.setVisible(status)
        self.actionPreview.setVisible(status)
        self.ckretencion.setEnabled(not status)
        self.ckIva.setEnabled(not status)
        self.conceptowidget.setCurrentIndex(1 if not status else 0)
        self.beneficiariowidget.setCurrentIndex(1 if not status else 0)
        self.cuentawidget.setCurrentIndex(1 if not status else 0)

        if not status:
            self.total.setText("0.0")
            self.subtotal.setValue(0)
            self.iva.setText("0.0")
            self.retencion.setText("0.0")
            self.txtobservaciones.setPlainText("")
            self.editmodel.uid = self.user.uid
            self.tabledetails.addAction(self.actionDeleteRow)
        else:
            self.tabledetails.removeAction(self.actionDeleteRow)

    def deleteRow(self):
        """
        Funcion usada para borrar lineas de la tabla
        """
        index = self.tabledetails.currentIndex()

        if not index.isValid():
            return
        row = index.row()

        self.editmodel.removeRows(row, 1)

    @pyqtSlot(bool)
    @if_edit_model
    def on_ckretencion_toggled(self, on):
        """
        """
        if on:
            self.retencionwidget.setCurrentIndex(1)
            self.editmodel.hasretencion = True
        else:
            self.retencionwidget.setCurrentIndex(0)
            self.cboretencion.setCurrentIndex(-1)
            self.editmodel.hasretencion = False
        # self.cboretencion.

    @pyqtSlot(bool)
    @if_edit_model
    def on_ckIva_toggled(self, on):
        """
        """
        # Verificar IVA
        query = QSqlQuery(
            """
                SELECT idcostoagregado, valorcosto 
                FROM costosagregados c 
                WHERE idtipocosto = 1 AND activo = 1 
                ORDER BY idtipocosto;
                """
        )
        query.exec_()
        if not query.size() == 1:
            QMessageBox.information(self, qApp.organizationName(), "No fue posible obtener el porcentaje " + "del IVA")
        if on:
            self.editmodel.hasiva = True
            query.first()
            self.editmodel.ivaId = query.value(0).toInt()[0]

        else:
            self.editmodel.hasiva = False

        self.updateTotals()

    @pyqtSlot(int)
    @if_edit_model
    def on_cboconcepto_currentIndexChanged(self, index):
        self.editmodel.conceptoId = self.conceptosmodel.record(index).value("idconcepto").toInt()[0]

    @pyqtSlot(int)
    @if_edit_model
    def on_cbocuenta_currentIndexChanged(self, index):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("Hubo un error al conectarse con la base de datos")

            self.editmodel.setData(
                self.editmodel.index(0, 2),
                [
                    self.cuentabancaria.record(index).value("idcuentacontable").toInt()[0],
                    self.cuentabancaria.record(index).value("codigo").toString(),
                    self.cuentabancaria.record(index).value("descripcion").toString(),
                ],
            )
            self.accountseditdelegate.accounts.setFilterRegExp(
                "[^%d]" % self.cuentabancaria.record(index).value("idcuentacontable").toInt()[0]
            )

            self.editmodel.moneda = self.cuentabancaria.record(index).value("IDMONEDA").toInt()[0]
            self.editmodel.simbolo = self.cuentabancaria.record(index).value("simbolo").toString()
            # Cargar el numero del cheque actual
            if index > -1:
                query = QSqlQuery(
                    """
                CALL spConsecutivo(12,"""
                    + self.cuentabancaria.record(index).value("idcuentacontable").toString()
                    + ")"
                )
                if not query.exec_():
                    raise UserWarning("No se pudo obtener el numero consecutivo del cheque")
                query.first()
                n = query.value(0).toString()

                self.lblncheque.setText(n)
                self.editmodel.printedDocumentNumber = n

                self.editmodel.setData(self.editmodel.index(0, 3), self.editmodel.totalCordobas)
                self.updateTotals()

        except UserWarning as inst:
            logging.error(inst)
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(inst)

    @pyqtSlot(int)
    @if_edit_model
    def on_cboretencion_currentIndexChanged(self, index):
        self.editmodel.retencionId = self.retencionModel.record(index).value("idcostoagregado").toInt()[0]
        self.editmodel.retencionPorcentaje = (
            Decimal(self.cboretencion.currentText()) if self.cboretencion.currentText() != "" else 0
        )
        self.updateTotals()

    @pyqtSlot(int)
    @if_edit_model
    def on_cbobeneficiario_currentIndexChanged(self, index):
        self.editmodel.proveedorId = self.proveedoresmodel.record(index).value("idpersona").toInt()[0]

    @pyqtSlot(float)
    @if_edit_model
    def on_subtotal_valueChanged(self, _index):
        self.updateTotals()

    def updateTotals(self):
        self.editmodel.subtotal = Decimal(str(self.subtotal.value()))
        self.editmodel.setData(self.editmodel.index(0, 3), self.editmodel.totalCordobas.quantize(Decimal("0.0001")))

        if self.editmodel.moneda == constantes.IDCORDOBAS:

            self.total.setText(moneyfmt(self.editmodel.totalCordobas, 4, self.editmodel.simbolo))
            self.iva.setText(moneyfmt(self.editmodel.iva, 4, self.editmodel.simbolo))
            self.retencion.setText(moneyfmt(self.editmodel.retencion, 4, self.editmodel.simbolo))

            self.total.setToolTip(moneyfmt(self.editmodel.totalDolares, 4, "US$"))
            self.iva.setToolTip(moneyfmt(self.editmodel.iva, 4, "US$"))
            self.retencion.setToolTip(moneyfmt(self.editmodel.retencion, 4, "US$"))

        elif self.editmodel.moneda == constantes.IDDOLARES:
            self.total.setText(moneyfmt(self.editmodel.totalDolares, 4, "US$"))
            self.iva.setText(moneyfmt(self.editmodel.iva, 4, "US$"))
            self.retencion.setText(moneyfmt(self.editmodel.retencion, 4, "US$"))

            self.total.setToolTip(moneyfmt(self.editmodel.totalCordobas, 4, "C$"))
            self.iva.setToolTip(moneyfmt(self.editmodel.iva, 4, "C$"))
            self.retencion.setToolTip(moneyfmt(self.editmodel.retencion, 4, "C$"))

    def cancel(self):
        """
        Aca se cancela la edicion del documento
        """
        self.editmodel = None
        self.tablenavigation.setModel(self.navproxymodel)
        self.tabledetails.setModel(self.accountsProxyModel)
        self.tabledetails.setColumnHidden(IDCUENTA, True)

        self.status = True
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning(u"No se pudo establecer la conexión con la base de datos")

            self.updateModels()
            self.navigate("last")
        except UserWarning as inst:
            QMessageBox.warning(self, qApp.organizationName(), inst)
            logging.critical(unicode(inst))
            self.status = True

    @property
    def printIdentifier(self):
        return self.navmodel.record(self.mapper.currentIndex()).value("iddocumento").toString()

    def newDocument(self):
        """
        activar todos los controles, llenar los modelos necesarios, 
        crear el modelo ChequeModel
        """
        self.tabWidget.setCurrentIndex(0)
        query = QSqlQuery()
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning(u"No se pudo establecer la conexión " + "con la base de datos")

            # Crea modelo para edicion
            self.editmodel = ChequeModel()

            # Sacar valor porcentaje del IVA
            query = QSqlQuery(
                """SELECT 
                valorcosto
            FROM costosagregados c 
            WHERE activo=1 AND idtipocosto=%d
            """
                % (constantes.IVA)
            )

            if not query.exec_():
                raise UserWarning("No se pudo ejecutar la consulta para" + " obtener los valores de los impuestos")
            elif not query.size() > 0:
                raise UserWarning("No se pudieron obtener los valores" + " de los impuestos")
            query.first()
            self.editmodel.ivaRate = Decimal(query.value(0).toString())

            self.dtPicker.setDateTime(QDateTime.currentDateTime())
            self.lbltipocambio.setText(str(self.editmodel.exchangeRate))

            #        Crea un edit delegate para las cuentas
            self.accountseditdelegate = ChequesFiltroDelegate(
                QSqlQuery(
                    """
            SELECT c.idcuenta, c.codigo, c.descripcion 
            FROM cuentascontables c 
            JOIN cuentascontables p ON c.padre = p.idcuenta AND p.padre != 1
            WHERE c.padre != 1 AND c.idcuenta != 22
            """
                )
            )
            self.tabledetails.setItemDelegate(self.accountseditdelegate)
            self.tabledetails.setModel(self.editmodel)

            #            Rellenar el combobox de las retenciones
            self.retencionModel = QSqlQueryModel()
            self.retencionModel.setQuery(
                """             
                    SELECT
                        idcostoagregado, 
                        FORMAT(valorcosto,0) as tasa 
                    FROM costosagregados 
                    WHERE idtipocosto IN (%d,%d) AND 
                    activo=1 
                    ORDER BY valorcosto desc; 
                    """
                % (constantes.RETENCIONPROFESIONALES, constantes.RETENCIONFUENTE)
            )

            self.cboretencion.setModel(self.retencionModel)
            self.cboretencion.setCurrentIndex(-1)
            self.cboretencion.setModelColumn(1)

            #       Rellenar el combobox de los PROVEEDORES
            self.proveedoresmodel = QSqlQueryModel()
            self.proveedoresmodel.setQuery(
                """
              SELECT
                    p.idpersona,
                    p.nombre,
                    p.activo
                    FROM personas p
                    where p.tipopersona=%d
                    group by p.idpersona
                    ORDER BY p.nombre
                    ;
            """
                % constantes.PROVEEDOR
            )

            self.proveedoresfiltro = QSortFilterProxyModel()
            self.proveedoresfiltro.setSourceModel(self.proveedoresmodel)
            self.proveedoresfiltro.setFilterKeyColumn(1)
            #        self.proveedoresfiltro.setFilterRegExp("0")
            self.cbobeneficiario.setModel(self.proveedoresfiltro)
            self.cbobeneficiario.setCurrentIndex(-1)
            self.cbobeneficiario.setModelColumn(1)

            completer = QCompleter()
            completer.setCaseSensitivity(Qt.CaseInsensitive)
            completer.setModel(self.proveedoresmodel)
            completer.setCompletionColumn(1)

            #       Rellenar el combobox de los conceptos
            self.conceptosmodel = QSqlQueryModel()
            self.conceptosmodel.setQuery(
                """
              SELECT idconcepto,descripcion 
              FROM conceptos c;
            """
            )
            self.cboconcepto.setModel(self.conceptosmodel)
            self.cboconcepto.setCurrentIndex(-1)
            self.cboconcepto.setModelColumn(1)

            completer = QCompleter()
            completer.setCaseSensitivity(Qt.CaseInsensitive)
            completer.setModel(self.conceptosmodel)
            completer.setCompletionColumn(1)

            self.cuentabancaria = QSqlQueryModel()
            # self.status = False
            #            Rellenar el combobox de las CONCEPTOS

            self.cuentabancaria.setQuery(
                u"""
                 SELECT
                   idcuentacontable,
                   cc.codigo,
                   CONCAT(cc.descripcion,"  Moneda: ",tm.moneda) as Descripción,
                   tm.moneda as Moneda,
                   tm.simbolo as simbolo,
                   tm.idtipomoneda as IDMONEDA
               FROM cuentasbancarias c
               JOIN cuentascontables cc ON cc.idcuenta=c.idcuentacontable
               JOIN tiposmoneda tm ON tm.idtipomoneda=c.idtipomoneda
               JOIN cuentasxdocumento cd ON cd.idcuenta=cc.idcuenta
               GROUP BY cc.idcuenta;
            """
            )
            if self.cuentabancaria.rowCount() < 0:
                QMessageBox.warning(self, qApp.organizationName(), u"Saldo insuficiente en cuentas bancarias")
            line = AccountsSelectorLine()
            record = self.cuentabancaria.record(self.cbocuenta.currentIndex())
            line.itemId = record.value("idcuentacontable").toInt()[0]
            line.code = record.value("codigo").toString()
            line.name = record.value("descripcion").toString()
            line.amount = Decimal(str(self.subtotal.value()))

            self.editmodel.insertRow(0)
            self.editmodel.lines[0] = line

            self.cbocuenta.setModel(self.cuentabancaria)
            self.cbocuenta.setCurrentIndex(-1)
            self.cbocuenta.setModelColumn(2)

            self.tabledetails.resizeColumnsToContents()
            self.tabledetails.setColumnHidden(0, True)

            completercuenta = QCompleter()
            completercuenta.setCaseSensitivity(Qt.CaseInsensitive)
            completercuenta.setModel(self.cuentabancaria)
            completercuenta.setCompletionColumn(1)

            self.lblretencion.setText("")

            self.status = False

        #            self.subtotal.valueChanged[float].connect( self.updateTotals )
        except UserWarning as inst:
            logging.error(unicode(inst))
            QMessageBox.warning(self, qApp.organizationName(), unicode(inst))
            self.status = True
        except Exception as inst:
            QMessageBox.warning(self, qApp.organizationName(), u"No se pudo iniciar la creación " "del nuevo cheque")
            logging.critical(unicode(inst))
            self.status = True
        finally:
            if self.database.isOpen():
                self.database.close()

    @pyqtSlot(QDateTime)
    def on_dtPicker_dateTimeChanged(self, datetime):
        """
        Asignar la fecha al objeto __document
        """
        if self.editmodel is not None:
            super(FrmCheques, self).on_dtPicker_dateTimeChanged(datetime)
            self.lbltipocambio.setText(str(self.editmodel.exchangeRate))

    @pyqtSlot()
    def anular(self):
        """
        @var: El elemento actual en el navmodel
        @type: QSqlRecord
        """

        record = self.navmodel.record(self.mapper.currentIndex())
        doc = record.value("iddocumento").toInt()[0]
        total = Decimal(record.value("TotalCheque").toString())

        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise Exception("No se pudo abrir la Base de datos")

            if (
                QMessageBox.question(
                    self,
                    qApp.organizationName(),
                    u"¿Esta seguro que desea anular el cheque?",
                    QMessageBox.Yes | QMessageBox.No,
                )
                == QMessageBox.Yes
            ):

                anulardialog = Anular(self.navmodel.record(self.mapper.currentIndex()).value("No. Cheque").toString())
                if anulardialog.conceptosmodel.rowCount() == 0:
                    QMessageBox.warning(self, qApp.organizationName(), u"No existen conceptos para la anulación")
                else:
                    if anulardialog.exec_() == QDialog.Accepted:
                        if (
                            anulardialog.cboConceptos.currentIndex() == -1
                            and anulardialog.txtObservaciones.toPlainText() == ""
                        ):
                            QMessageBox.critical(self, qApp.organizationName(), "Por favor rellene todos los campos")
                        else:
                            query = QSqlQuery()
                            if not self.database.transaction():
                                raise Exception(u"No se pudo comenzar la transacción")
                            #
                            query = QSqlQuery(
                                """
                                SELECT fnConsecutivo(%d,NULL);
                                """
                                % constantes.IDANULACION
                            )
                            if not query.exec_():
                                raise Exception("No se pudo obtener el numero de la factura")
                            query.first()
                            n = query.value(0).toString()
                            # Insertar documento anulacion
                            if not query.prepare(
                                """
                            INSERT INTO documentos(ndocimpreso,total,fechacreacion,idtipodoc,observacion,idestado)
                            VALUES(:ndocimpreso,:total,:fechacreacion,:idtipodoc,:observacion,:idestado)"""
                            ):
                                raise Exception(query.lastError().text())

                            query.bindValue(":ndocimpreso", n)
                            query.bindValue(":total", total.to_eng_string())
                            query.bindValue(":fechacreacion", QDate.currentDate())
                            query.bindValue(":idtipodoc", constantes.IDANULACION)
                            query.bindValue(":observacion", anulardialog.txtObservaciones.toPlainText())
                            query.bindValue(":idestado", constantes.CONFIRMADO)

                            if not query.exec_():
                                raise Exception("No se pudo insertar el documento Anulacion")

                            idanulacion = query.lastInsertId().toString()

                            query.prepare("CALL spEliminarCheque(:doc,:anulado,:idcheque,:idretencion)")
                            query.bindValue(":doc", idanulacion)
                            query.bindValue(":idcheque", doc)
                            query.bindValue(":anulado", constantes.ANULADO)
                            query.bindValue(":idretencion", constantes.IDRETENCION)
                            if not query.exec_():
                                raise UserWarning("No se pudo Anular el Cheque")

                            if not query.prepare(
                                "INSERT INTO docpadrehijos (idpadre,idhijo) VALUES" + "(:idcheque," + idanulacion + ")"
                            ):
                                #                                "(:usuario," + insertedId + ",0),"
                                #                                "(:supervisor," + insertedId + ",1)"):
                                raise Exception(
                                    query.lastError().text() + "No se preparo la relacion de la anulacion con el Cheque"
                                )

                            query.bindValue(":idcheque", doc)

                            if not query.exec_():
                                raise Exception("No se pudo insertar la relacion de la Anulacion con el Cheque")

                            if not query.prepare(
                                "INSERT INTO personasxdocumento (idpersona,iddocumento,idaccion) VALUES"
                                + "(:usuario,"
                                + idanulacion
                                + ",:accion)"
                            ):
                                raise Exception(query.lastError().text() + "No se inserto el usuario y autoriza")

                            query.bindValue(":usuario", self.user.uid)
                            query.bindValue(":accion", constantes.AUTOR)

                            if not query.exec_():
                                raise Exception("No se pudo Insertar la relacion de la anulacion con el usuario")

                            if not self.database.commit():
                                raise Exception("NO se hizo el commit para la Anulacion")
                            QMessageBox.information(
                                self, qApp.organizationName(), "Cheque anulado Correctamente", QMessageBox.Ok
                            )
                            self.updateModels()
        except UserWarning as inst:
            logging.error(unicode(inst))
            logging.error(query.lastError().text())
            self.database.rollback()
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(unicode(inst))
            logging.critical(query.lastError().text())
            self.database.rollback()
        finally:
            if self.database.isOpen():
                self.database.close()

    def save(self):
        """
        Guardar el documento actual
        """
        query = QSqlQuery(
            """
        SELECT
            cc.idcuenta,
            SUM(IFNULL(monto,0)) monto
        FROM cuentascontables cc
        LEFT JOIN cuentascontables ch ON cc.idcuenta = ch.padre
        LEFT JOIN cuentasxdocumento cxd ON cc.idcuenta = cxd.idcuenta
        WHERE cc.idcuenta = %d"""
            % (self.cuentabancaria.record(self.cbocuenta.currentIndex()).value("idcuentacontable").toInt()[0])
        )
        query.exec_()
        query.first()
        totalcuenta = query.value(1).toString()
        if Decimal(str(self.subtotal.value())) > Decimal(totalcuenta):
            QMessageBox.warning(self, qApp.organizationName(), "No existe suficiente saldo para crear" + " el cheque")

        if (
            QMessageBox.question(
                self, qApp.organizationName(), u"¿Esta seguro que desea guardar?", QMessageBox.Yes | QMessageBox.No
            )
            == QMessageBox.Yes
        ):

            if self.editmodel.valid:
                if self.editmodel.save():
                    QMessageBox.information(self, qApp.organizationName(), u"El documento se ha guardado con éxito")
                    self.editmodel = None
                    self.updateModels()
                    self.navigate("last")
                    self.status = True
                else:
                    QMessageBox.critical(self, qApp.organizationName(), "Ha ocurrido un error al guardar el documento")

            else:
                try:
                    QMessageBox.warning(self, qApp.organizationName(), self.editmodel.validError)
                except AttributeError:
                    QMessageBox.warning(
                        self,
                        qApp.organizationName(),
                        u"El documento no puede guardarse ya " + "que la información no esta completa",
                    )
Ejemplo n.º 13
0
class dlgPersona( QDialog, Ui_dlgPersona ):
        
    def __init__( self ,tipopersona, parent ):
        '''
        Constructor
        '''
        super( dlgPersona, self ).__init__( parent )
        self.setupUi(self)

#        self.tableview.addActions( ( self.actionEdit, self.actionNew ) )
        self.idtipopersona = tipopersona
        self.table = ""
        self.backmodel = QSqlQueryModel()
        self.database = parent.database

        self.filtermodel = QSortFilterProxyModel( self )
        self.filtermodel.setSourceModel( self.backmodel )
        self.filtermodel.setDynamicSortFilter( True )
        self.filtermodel.setFilterKeyColumn( -1 )
        self.filtermodel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        
        self.paisesModel = QSqlQueryModel()
        self.cbpais.setModel( self.paisesModel )
        self.cbpais.setCurrentIndex( -1 )
        self.cbpais.setFocus()
        self.cbpais.setModelColumn( 1 )
        self.paisescompleter = QCompleter()
        self.paisescompleter.setCaseSensitivity( Qt.CaseInsensitive )
        self.paisescompleter.setModel( self.paisesModel )
        self.paisescompleter.setCompletionColumn( 1 )
        self.cbpais.setCompleter( self.paisescompleter )      


        self.proveedoresModel = QSqlQueryModel()
        self.cbproveedor.setModel( self.proveedoresModel )
        self.cbproveedor.setCurrentIndex( -1 )
        self.cbproveedor.setFocus()
        self.cbproveedor.setModelColumn( 1 )
        self.proveedorcompleter = QCompleter()
        self.proveedorcompleter.setCaseSensitivity( Qt.CaseInsensitive )
        self.proveedorcompleter.setModel( self.proveedoresModel )
        self.proveedorcompleter.setCompletionColumn( 1 )
        self.cbproveedor.setCompleter( self.proveedorcompleter ) 


#        self.tableview.setModel(self.filtermodel)
        self.cbsexo.setCurrentIndex(-1)
        self.txtnombre.setFocus()
        self.setReadOnly(True)
        QTimer.singleShot( 0, self.updateModels )
       
    @pyqtSlot( "QString" )
    def on_txtSearch_textChanged( self, text ):
        """
        Cambiar el filtro de busqueda
        """
        self.filtermodel.setFilterRegExp( text )
       
    def setReadOnly(self,status):
        self.txtSearch.setText("")
        self.txtnombre.setText("")
        self.txtempresa.setText("")
        self.txttelefono.setText("")
        self.txtcorreo.setText("")
        self.cbpais.setCurrentIndex(-1)
        self.txtnombre.setFocus()
        if status:
            self.editmodel = None
            self.swpanel.setCurrentIndex(0)
        else:
            
            self.editmodel = PersonaModel(self.database,self.idtipopersona)
            self.swpanel.setCurrentIndex(1)
            

#
#        if status:
#            self.tableview.setEditTriggers( QAbstractItemView.AllEditTriggers )
##            self.tableview.edit( self.tableview.selectionModel().currentIndex() )
#        else:
#            self.tableview.setEditTriggers( QAbstractItemView.NoEditTriggers )
#
#        self.actionNew.setVisible(  status )
#        self.actionEdit.setVisible(  status )
#        self.actionDelete.setVisible( status )
#        self.actionCancel.setVisible( not status )
#        self.actionSave.setVisible(not  status )
#        self.backmodel.readOnly = status


    def updateModels( self ):
        """
        Actualizar los modelos, despues de toda operacion que cambie la base de datos se tienen que actualizar los modelos
        """

        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo conectar con la base de datos" )
            self.backmodel.setQuery("""
            SELECT
                d.idpersona as Id,
                d.Nombre,
                d.Telefono,
                d.Correo,
                p.nombre as Pais
         FROM personas d JOIN paises p ON p.idpais = d.idpais
         WHERE idaccion = %d""" %self.idtipopersona )
            
            self.tableview.setModel( self.filtermodel )
            
            self.tableview.setColumnHidden(0,True)
#            self.tableview.setColumnWidth(0,200)
#            self.tableview.set


            self.paisesModel.setQuery( """
            SELECT idpais , nombre  
            FROM paises  """  )
            
            if self.paisesModel.rowCount() == 0:
                raise UserWarning( "No existen paises en la"\
                              + " base de datos" )
            self.cbpais.setModel( self.paisesModel )
            self.cbpais.setCurrentIndex( -1 )
            self.cbpais.setModelColumn( 1 )

            self.paisescompleter.setCaseSensitivity( Qt.CaseInsensitive )
            self.paisescompleter.setModel( self.paisesModel )
            self.paisescompleter.setCompletionColumn( 1 )
            self.cbpais.setCompleter( self.paisescompleter )
            
            self.proveedoresModel.setQuery( """
            SELECT 
            idproveedor, nombre 
            FROM proveedores p where p.idproveedor not in (select origen from proveedores where origen is not null);""" )
            
            if self.proveedoresModel.rowCount() == 0:
                raise UserWarning( "No existen proveedores en la"\
                              + " base de datos" )
            self.cbproveedor.setModel( self.proveedoresModel )
            self.cbproveedor.setCurrentIndex( -1 )
            self.cbproveedor.setFocus()
            self.cbproveedor.setModelColumn( 1 )

            self.proveedorcompleter.setCaseSensitivity( Qt.CaseInsensitive )
            self.proveedorcompleter.setModel( self.proveedoresModel )
            self.proveedorcompleter.setCompletionColumn( 1 )
            self.cbproveedor.setCompleter( self.proveedorcompleter )
            self.cbproveedor.setModel( self.proveedoresModel )
            self.cbproveedor.setCurrentIndex(-1)            
            self.database.close()
        except Exception as inst:
            print( unicode( inst ) )
            return False
        finally:
            if self.database.isOpen():
                self.database.close()
        return True
 
 
    @pyqtSlot()
    def on_btnadd_clicked(self):
        self.setReadOnly(False)
        
    @pyqtSlot()
    def on_btnagregar_pais_clicked(self):
        paisdialog = DlgPais(self)
        paisdialog.exec_()
        self.updateModels()
        
    @pyqtSlot()
    def on_btncancelar_clicked(self):
        self.setReadOnly(True)
  
    @pyqtSlot( int )
    def on_cbproveedor_currentIndexChanged( self, index ):
        """
        asignar la concepto al objeto self.editmodel
        """
        if self.editmodel is not None:
            self.editmodel.idproveedor = self.proveedoresModel.record( index ).value( "idproveedor" ).toInt()[0]
    
    @pyqtSlot( int )
    def on_cbpais_currentIndexChanged( self, index ):
        """
        asignar la concepto al objeto self.editmodel
        """
        if self.editmodel is not None:
            self.editmodel.idpais = self.paisesModel.record( index ).value( "idpais" ).toInt()[0]
        
    @pyqtSlot()
    def on_btnguardar_clicked(self): 
        self.editmodel.nombre = self.txtnombre.text()
        self.editmodel.telefono = self.txttelefono.text()
        self.editmodel.correo = self.txtcorreo.text()
        self.editmodel.empresa = self.txtempresa.text()
        self.editmodel.eshombre = self.cbsexo.currentIndex()
        self.editmodel.descuento = self.txtdescuento.value()
        
        if self.editmodel.valid():
            if self.editmodel.save():
                QMessageBox.information(None,"Guardar", self.editmodel.mensaje)
                self.setReadOnly(True)
                self.updateModels()
            else:
                QMessageBox.critical(None,"Guardar", self.editmodel.mensaje)
        else:
            QMessageBox.critical(None,"Guardar", self.editmodel.mensaje)    
            
    @pyqtSlot( int )
    def on_cbproveedor_currentIndexChanged( self, index ):
        """
        asignar la concepto al objeto self.editmodel
        """
        if self.editmodel is not None:
            self.editmodel.idproveedor = self.proveedoresModel.record( index ).value( "idproveedor" ).toInt()[0]
Ejemplo n.º 14
0
class FrmRecibo( Ui_frmRecibo, Base ):
    """
    Implementacion de la interfaz grafica para entrada compra
    """
    web = "recibos.php?doc="

    def __init__( self, parent = None ):
        '''
        Constructor
        '''
        super( FrmRecibo, self ).__init__( parent )



#       las acciones deberian de estar ocultas
        self.frbotones.setVisible( False )
        self.actionSave.setVisible( False )
        self.actionCancel.setVisible( False )

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#        El modelo principal
        self.navmodel = QSqlQueryModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = RONavigationModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        

#        Este es el modelo con los datos de la con los detalles
        self.detailsmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#        Este es el modelo con los datos de la con los detalles
        self.abonosmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.abonosproxymodel = QSortFilterProxyModel( self )
        self.abonosproxymodel.setSourceModel( self.abonosmodel )
        self.facturasmodel = QSqlQueryModel( self )
        self.facturasproxymodel = ROFacturasModel( self )
        self.facturasproxymodel.setSourceModel( self.facturasmodel )

        #inicializando el documento
        self.editmodel = None
        self.datosRecibo = None

        self.status = True

        QTimer.singleShot( 0, self.loadModels )

    def agregarFactura( self, i, n ):
#        modelo = cindex.model()
        modelo = self.facturasproxymodel
        self.abonoeditmodel.insertRows( i )
        self.abonoeditmodel.lines[i].idFac = modelo.index( n, 0 ).data()
        self.abonoeditmodel.lines[i].nFac = modelo.index( n, 1 ).data()
        monto = Decimal( modelo.data( modelo.index( n, 2 ), Qt.EditRole ).toString() )

        self.abonoeditmodel.lines[i].tasaIva = Decimal( modelo.data( modelo.index( n, 3 ), Qt.EditRole ).toString() )
        self.abonoeditmodel.lines[i].monto = monto
#        self.abonoeditmodel.lines[i].setMonto( monto)


        self.abonoeditmodel.lines[i].nlinea = n

        self.abonoeditmodel.lines[i].totalFac = monto
        self.tablefacturas.setRowHidden( n, True )

    def cancel( self ):
        """
        Aca se cancela la edicion del documento
        """
        self.status = True

    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex() ).value( "iddocumento" ).toString()

    def newDocument( self ):
        """
        activar todos los controles, llenar los modelos necesarios, crear el modelo EntradaCompraModel, aniadir una linea a la tabla
        """
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo establecer la conexión"\
                                       + " con la base de datos" )

            self.facturasmodel.setQuery( """          
            SELECT
                s.iddocumento,
                s.ndocimpreso,
                s.Saldo,
                s.tasaiva,
                s.idpersona
            FROM vw_saldofacturas s
            WHERE s.saldo>0 and s.idestado = %d
            ;
        """ % constantes.CONFIRMADO )

            self.tablefacturas.setModel( self.facturasproxymodel )
            self.tablefacturas.setColumnHidden( IDDOCUMENTO, True )
#            self.tablefacturas.setColumnHidden( 3, True )

#            Rellenar el combobox de los CLLIENTES
            self.clientesModel = QSqlQueryModel()
            self.clientesModel.setQuery( """
            SELECT
            s.idpersona,
            s.nombre
            FROM vw_saldofacturas s
            WHERE s.idestado = %d
            GROUP BY s.idpersona
            HAVING SUM(s.saldo)>0
            ORDER BY s.nombre
            """ % constantes.CONFIRMADO )
#Verificar si existen clientes morosos            
            if self.clientesModel.rowCount() == 0:
                raise UserWarning( "No existen clientes morosos" )

#            Rellenar el combobox de las CONCEPTOS
            self.conceptosModel = QSqlQueryModel()
            self.conceptosModel.setQuery( """
               SELECT idconcepto, descripcion 
               FROM conceptos c 
               WHERE idtipodoc = %d;
            """ % constantes.IDRECIBO )
            if self.conceptosModel.rowCount() == 0:
                raise UserWarning( "No existen conceptos para los recibos,"\
                                        + " por favor cree uno" )



            self.cbcliente.setModel( self.clientesModel )
            self.cbcliente.setCurrentIndex( -1 )
            self.cbcliente.setModelColumn( 1 )
            completer = QCompleter()
            completer.setCaseSensitivity( Qt.CaseInsensitive )
            completer.setModel( self.clientesModel )
            completer.setCompletionColumn( 1 )


            self.cbconcepto.setModel( self.conceptosModel )
            self.cbconcepto.setCurrentIndex( -1 )
            self.cbconcepto.setModelColumn( 1 )
            completerconcepto = QCompleter()
            completerconcepto.setCaseSensitivity( Qt.CaseInsensitive )
            completerconcepto.setModel( self.conceptosModel )
            completerconcepto.setCompletionColumn( 1 )

            self.datosRecibo = DatosRecibo( self.parentWindow.datosSesion )
            self.editmodel = ReciboModel( self.datosRecibo.lineas, self.datosRecibo.datosSesion.tipoCambioBanco )
            self.abonoeditmodel = AbonoModel( self.datosRecibo.lineasAbonos )


            self.datosRecibo.cargarRetenciones( self.cbtasaret )

            if self.datosRecibo.retencionModel.rowCount() == 0:
                raise UserWarning( u"No existe ninguna tasa de retención."\
                                      + " Por favor contacte al administrador"\
                                      + " del sistema" )
# Asigno el modelo del recibo
            self.datosRecibo.cargarNumeros( self )

            self.tablefacturas.setSelectionMode( QAbstractItemView.SingleSelection )
            self.tablefacturas.setSelectionBehavior( QAbstractItemView.SelectRows )
            self.tableabonos.setModel( self.abonoeditmodel )
            self.tabledetails.setModel( self.editmodel )

# ASIGNO EL DELEGADO A LA TABLA DE LOS PAGO            
            delegate = ReciboDelegate()
            self.tabledetails.setItemDelegate( delegate )


# ASIGNO EL DELEGADO A LA TABLA DE LOS ABONOS
            delegado = AbonoDelegate()
            self.tableabonos.setItemDelegate( delegado )

            self.status = False
            self.frbotones.setVisible( True )
            self.updateFacturasFilter()

            self.abonoeditmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                  u"Hubo un error al tratar de obtener los datos" )
        finally:
            if self.database.isOpen():
                self.database.close()


    def save( self ):
        """
        Slot documentation goes here.
        """
#        self.datosRecibo.lineasAbonos =self.abonoeditmodel.lines
#        self.datosRecibo.lineas = self.editmodel.lines
        self.datosRecibo.observaciones = self.txtobservaciones.toPlainText()
        if self.datosRecibo.valid( self ):
            if QMessageBox.question( self, qApp.organizationName(),
                                 u"¿Esta seguro que desea guardar el recibo?",
                                 QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
                if not QSqlDatabase.database().isOpen():
                    QSqlDatabase.database().open()


                if self.datosRecibo.save():
                    QMessageBox.information( self,
                        qApp.organizationName() ,
                         u"""El documento se ha guardado con éxito""" )
                    self.editmodel = None
                    self.updateModels()
                    self.navigate( 'last' )
                    self.status = True
                else:
                    QMessageBox.critical( self,
                         qApp.organizationName(),
                         """Ha ocurrido un error al guardar el documento""" )

                if self.database.isOpen():
                    self.database.close()


    @pyqtSlot( bool )
    def on_btnadd_clicked( self, _on ):
        """
        Asignar el contenido al objeto documeto
        """
        cindex = self.tablefacturas.currentIndex()
        if not cindex.model() is None:
            if not self.tablefacturas.isRowHidden( cindex.row() ):
                i = self.abonoeditmodel.rowCount()
                self.agregarFactura( i, cindex.row() )
                self.updateLabels()



    @pyqtSlot( bool )
    def on_btnaddall_clicked( self, _on ):
        """
        Asignar el contenido al objeto documeto
        """
        i = self.abonoeditmodel.rowCount()
        for n in range( self.facturasproxymodel.rowCount() ):
            if not self.tablefacturas.isRowHidden( n ):
                self.agregarFactura( i, n )
                i = i + 1
        self.updateLabels()


    @pyqtSlot( bool )
    def on_btnremove_clicked( self, _on ):
        """
        Asignar el contenido al objeto documeto
        """
        r = self.tableabonos.currentIndex().row()
        if self.abonoeditmodel.rowCount() > 0 and r > -1:
            self.abonoeditmodel.removeRows( r, self.tablefacturas )
            self.updateLabels()

    @pyqtSlot( bool )
    def on_btnremoveall_clicked( self, _on ):
        """
        Asignar el contenido al objeto documeto
        """
        rows = self.abonoeditmodel.rowCount()
        if  rows > 0:
            self.abonoeditmodel.removeRows( 0, self.tablefacturas, rows )
            self.updateLabels()


    @pyqtSlot( int )
    @if_edit_model
    def on_cbcliente_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.datosRecibo.clienteId = self.clientesModel.record( index ).value( "idpersona" ).toInt()[0] if index != -1 else - 1
        self.tableabonos.setEnabled( index != -1 )
        self.frbotones.setEnabled( index != -1 )
        self.abonoeditmodel.removeRows( 0, self.tablefacturas,
                                         self.abonoeditmodel.rowCount() )
        self.abonoeditmodel.idcliente = self.datosRecibo.clienteId
        self.updateFacturasFilter()
        self.updateLabels()

    @pyqtSlot( int )
    @if_edit_model
    def on_cbconcepto_currentIndexChanged( self, index ):
        """
        asignar la concepto al objeto self.editmodel
        """
        self.datosRecibo.conceptoId = self.conceptosModel.record( index ).value( "idconcepto" ).toInt()[0]

    @pyqtSlot( int )
    def on_cbtasaret_currentIndexChanged( self, index ):
        """
        asignar la retencion al objeto self.editmodel
        """
        self.datosRecibo.tasaRetencionCambio( self, index )
        if self.ckretener.isEnabled():
            self.updateLabels()

# MANEJO EL EVENTO  DE SELECCION EN EL RADIOBUTTON
    @pyqtSlot( bool )
    @if_edit_model
    def on_ckretener_toggled( self, on ):
        """
        """
        self.datosRecibo.aplicarRet = on
        self.cbtasaret.setEnabled( on )
        self.cbtasaret.setCurrentIndex( -1 )

    @pyqtSlot( QDateTime )
    def on_dtPicker_dateTimeChanged( self, datetime ):
        pass

    def removeLine( self ):
        """
        Funcion usada para borrar lineas de la tabla
        """
        index = self.tabledetails.currentIndex()

        if not index.isValid():
            return
        row = index.row()

        self.tabledetails.removeRows( row )
        self.updateLabels()


    def setControls( self, status ):
        """
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible( status )
        self.dtPicker.setReadOnly( True )
#        self.ckretener.setEnabled( ( not status ) )
        self.txtobservaciones.setReadOnly( status )
        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )
        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionPreview.setVisible( status )
        self.ckretener.setEnabled( False )

        if status:
            self.editmodel = None
            self.frbotones.setVisible( False )
            self.tablenavigation.setModel( self.navproxymodel )
            self.tabledetails.setModel( self.detailsproxymodel )
            self.tableabonos.setModel( self.abonosproxymodel )

            self.tabledetails.setColumnHidden( IDPAGO, True )
            self.tabledetails.setColumnHidden( IDMONEDA, True )
            self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )

            self.swcliente.setCurrentIndex( 1 )
            self.swconcepto.setCurrentIndex( 1 )
            self.swtasaret.setCurrentIndex( 1 )
            self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers )
            self.tableabonos.setEditTriggers( QAbstractItemView.NoEditTriggers )
        else:
            self.tabWidget.setCurrentIndex( 0 )
            self.dtPicker.setDate( self.parentWindow.datosSesion.fecha )
            self.swcliente.setCurrentIndex( 0 )
            self.swconcepto.setCurrentIndex( 0 )
            self.swtasaret.setCurrentIndex( 0 )
            self.txtobservaciones.setPlainText( "" )
            self.lbltotalreten.setText( "US$ 0.0000" )
            self.lbltotal.setText( "US$ 0.0000" )
            self.lbltotalrecibo.setText( "US$ 0.0000" )
            self.cbcliente.setFocus()
            self.ckretener.setChecked( False )
            self.tabledetails.setEditTriggers( QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked )
            self.tableabonos.setEditTriggers( QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked )
            self.cbcliente.setCurrentIndex( -1 )


        self.tableabonos.setColumnHidden( IDDOCUMENTO, True )

        self.tabledetails.setColumnWidth( DESCRIPCION, 250 )
        self.tabledetails.setColumnWidth( MONTO, 150 )
        self.tabledetails.setColumnWidth( MONTODOLAR, 150 )
        self.tabledetails.setColumnWidth( REFERENCIA, 150 )


    def updateDetailFilter( self, index ):
        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        iddoc = self.navmodel.record( index ).value( "iddocumento" ).toString()
        self.detailsproxymodel.setFilterRegExp( iddoc )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )
# FILTRO DE LOS ABONOS
        self.abonosproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        self.abonosproxymodel.setFilterRegExp( iddoc )
        self.tabledetails.resizeColumnsToContents()



    def updateFacturasFilter( self ):
        self.facturasproxymodel.setFilterKeyColumn( IDCLIENTE )
        self.facturasproxymodel.setFilterRegExp( "^" + str( self.datosRecibo.clienteId ) + "$" )


    def updateLabels( self ):
        #Asingar el total al modelo
        totalAbono = self.abonoeditmodel.total

        retener = self.datosRecibo.retencionValida

        if self.cbtasaret.currentIndex() > -1 or ( not self.ckretener.isEnabled() ):
            self.ckretener.setChecked( retener )
        self.ckretener.setEnabled( retener )
        self.cbtasaret.setEnabled( retener )

        ret = self.datosRecibo.obtenerRetencion
        self.editmodel.asignarTotal( totalAbono - ret )
        tasa = self.datosRecibo.datosSesion.tipoCambioBanco

        self.lbltotal.setText( moneyfmt( totalAbono, 4, "US$ " ) )
        self.lbltotal.setToolTip( moneyfmt( totalAbono * tasa, 4, "C$ " ) )

        self.lbltotalreten.setText( moneyfmt( ret, 4, "US$ " ) )
        self.lbltotalreten.setToolTip( moneyfmt( ret * tasa, 4, "C$ " ) )

        self.lbltotalrecibo.setText( moneyfmt( totalAbono - ret, 4, "US$ " ) )
        self.lbltotalrecibo.setToolTip( moneyfmt( ( totalAbono - ret ) * tasa, 4, "C$ " ) )



    def updateModels( self ):
        """
        Recargar todos los modelos
        """
        try:

            if not QSqlDatabase.database().isOpen():
                QSqlDatabase.database().open()
    #        El modelo principal
            query = """
        SELECT
                            padre.iddocumento,
                            DATE(padre.fechacreacion) as 'Fecha',
                            padre.ndocimpreso as 'No. Recibo',
                            p.nombre as 'Cliente',
                            padre.total + IFNULL(hijo.total,0) as 'Total',
                            c.descripcion as 'En cocepto de',
                            IF(hijo.ndocimpreso IS NULL,'-',hijo.ndocimpreso) as 'No. Retencion',
                            IF(ca.valorcosto IS NULL, '-',CONCAT(CAST(ca.valorcosto AS CHAR),'%s')) as 'Retencion',
                            IFNULL(hijo.total,'-') as 'Total Ret C$',
                            padre.total as 'Total Pagado', 
                           padre.observacion ,
                           IF(hijo.iddocumento IS NULL, 0,1) as 'Con Retencion',
                        GROUP_CONCAT('(',fac.iddocumento, ')' SEPARATOR '') as idfacturas
            FROM documentos padre
            JOIN docpadrehijos phfac ON phfac.idhijo = padre.iddocumento
            JOIN documentos fac ON phfac.idpadre = fac.iddocumento AND fac.idtipodoc = %d
            JOIN personasxdocumento pxd ON pxd.iddocumento = padre.iddocumento
            JOIN personas p ON p.idpersona = pxd.idpersona
            JOIN conceptos c ON  c.idconcepto=padre.idconcepto
            LEFT JOIN costosxdocumento cd ON cd.iddocumento=padre.iddocumento
            LEFT JOIN  costosagregados ca ON ca.idcostoagregado=cd.idcostoagregado
            LEFT JOIN docpadrehijos ph ON  padre.iddocumento=ph.idpadre
            LEFT JOIN documentos hijo ON hijo.iddocumento=ph.idhijo
            WHERE padre.idtipodoc=%d
            AND p.tipopersona=%d
            GROUP BY padre.iddocumento
            ORDER BY padre.iddocumento;
            """ % ( '%', constantes.IDFACTURA, constantes.IDRECIBO, constantes.CLIENTE )
    
            self.navmodel.setQuery( query )
    
    # Proxy model que se utilizara desde el formulario de facturacion SOLAMENTE
            self.remoteProxyModel = QSortFilterProxyModel()
            self.remoteProxyModel.setSourceModel( self.navmodel )
            self.remoteProxyModel.setFilterKeyColumn( IDFACTURAS )
            self.remoteProxyModel.setFilterRegExp( '' )
    
    
    
            self.navproxymodel = RONavigationModel( self )
            self.navproxymodel.setSourceModel( self.remoteProxyModel )
            self.navproxymodel.setFilterKeyColumn( -1 )
            self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )
    
    #        Este es el modelo con los datos de la tabla para navegar
    #FIXME: Se el simbolo de la moneda deberia de salir desde la tabla tiposmoneda    
            self.detailsmodel.setQuery( """
                SELECT
                p.iddocumento,
                CONCAT(tp.descripcion, ' ' , tm.moneda) as 'Tipo de Pago',
                 p.refexterna as 'No. Referencia',
                 b.descripcion as Banco,
                 CONCAT(tm.simbolo,' ',FORMAT(monto,4)) as 'Monto',
                 CONCAT('US$ ',FORMAT(monto / IF(p.idtipomoneda=2,1,IFNULL(tc.tasaBanco,tc.tasa)),4)) as 'Monto US$'
            FROM movimientoscaja p
            JOIN documentos d ON d.iddocumento=p.iddocumento AND d.idtipodoc=18
            JOIN tiposcambio tc ON tc.idtc=d.idtipocambio
            JOIN tiposmoneda tm ON tm.idtipomoneda=p.idtipomoneda
            JOIN tiposmovimientocaja tp ON tp.idtipomovimiento=p.idtipomovimiento
            LEFT JOIN bancos b ON b.idbanco = p.idbanco
            ORDER BY p.nlinea
            ;
            """ )
    
    #        Este es el filtro del modelo anterior
            self.detailsproxymodel = QSortFilterProxyModel( self )
            self.detailsproxymodel.setSourceModel( self.detailsmodel )
            self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
            self.detailsproxymodel.setFilterRegExp( '^0$' )
    # ESTE ES EL MODELO CON LOS DATOS DE Los ABONOS PARA NAVEGAR
            self.abonosmodel = QSqlQueryModel( self )
            self.abonosmodel.setQuery( """
           SELECT
            d.idhijo as idrecibo,
            padre.ndocimpreso as 'No. Factura',
            CONCAT('US$ ',FORMAT(d.monto,4)) as 'Saldo'
            FROM docpadrehijos d
            JOIN documentos padre ON d.idpadre=padre.iddocumento
            WHERE padre.idtipodoc=%d and d.monto is not null
            ORDER BY d.nlinea
    ;
            """ % constantes.IDFACTURA )
    
    #        Este es el filtro del modelo anterior
            self.abonosproxymodel.setSourceModel( self.abonosmodel )
    
    
    #        Este objeto mapea una fila del modelo self.navproxymodel a los controles
            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )
            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.lblnrec, NDOCIMPRESO , "text" )
            self.mapper.addMapping( self.lblnreten, NRETENCION , "text" )
    
            self.mapper.addMapping( self.txtobservaciones, OBSERVACION )
            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.txtcliente, NOMBRECLIENTE, "text" )
            self.mapper.addMapping( self.txtconcepto, CONCEPTO, "text" )
            self.mapper.addMapping( self.lbltotalreten, TOTALRETENCION, "text" )
            self.mapper.addMapping( self.txttasaret, TASARETENCION, "text" )
            self.mapper.addMapping( self.lbltotal, TOTAL, "text" )
            self.mapper.addMapping( self.lbltotalrecibo, TOTALPAGADO, "text" )
            self.mapper.addMapping( self.ckretener, CONRETENCION, "checked" )
    
            self.tablenavigation.setColumnHidden( 0, True )
            self.tablenavigation.setColumnHidden( TOTALRETENCION, True )
            self.tablenavigation.setColumnHidden( CONRETENCION, True )
            
#            self.tabledetails.resizeColumnsToContents()

        except Exception as inst:
            pass
        finally:
            if QSqlDatabase.database().isOpen():
                QSqlDatabase.database().close()
Ejemplo n.º 15
0
class DlgApertura ( QDialog, Ui_dlgApertura ):
    def __init__( self, parent, cerrar = False ):
        """
        Constructor para agregar un nuevo articulo
        """
        super( DlgApertura, self ).__init__( parent )
        self.parentWindow = parent
        self.setupUi( self )
        
        self.fechaApertura = None
        self.capitalMaximo = Decimal(0)
        self.editmodel = AperturaModel( parent.datosSesion )
        
        self.cerrar = cerrar


        self.txtUsuario.setText( parent.user.user )
        self.txtUsuario.setReadOnly( True )

#        self.txtUser.setFocus()
        self.txtPassword.setEchoMode( QLineEdit.Password )
        self.setWindowIcon( QIcon( ":/icons/res/logo.png" ) )


        self.txtSaldoC.setAlignment( Qt.AlignRight )
        self.txtSaldoD.setAlignment( Qt.AlignRight )
        self.txtSaldoC.setPrefix("C$")
        self.txtSaldoD.setPrefix("US$")
        
        self.supervisor = None

        if cerrar:
            self.swcaja.setCurrentIndex( 1 )
            self.txtcaja.setText( parent.cajaNombre )
            self.txtcaja.setReadOnly( True )
            self.editmodel.cajaId = parent.datosSesion.cajaId

        else:
            self.swcaja.setCurrentIndex( 0 )
            self.cajasmodel = QSqlQueryModel()
            try:
                if not QSqlDatabase.database().isOpen():
                    if not QSqlDatabase.database().open():
                        raise UserWarning( u"No se pudo abrir la conexión "
                                           + "con la base de datos" )

                
                q = """
                SELECT
                    d.idcaja,
                    c.descripcion,
                    SUM(IF(m.idtipomoneda = %d,m.monto,0)) AS totalC,
                    SUM(IF(m.idtipomoneda = %d,m.monto,0)) AS totalD
                FROM
                movimientoscaja m
                JOIN documentos d ON d.iddocumento = m.iddocumento
                JOIN cajas c ON c.idcaja = d.idcaja
                WHERE d.idcaja is not null AND m.idtipomovimiento=%d
                GROUP BY  d.idcaja;""" % ( constantes.IDCORDOBAS,
                        constantes.IDDOLARES, constantes.IDPAGOEFECTIVO)
                self.cajasmodel.setQuery( q )
                if self.cajasmodel.rowCount() == 0:
                    q = """
                    SELECT
                        c.idcaja,
                        c.descripcion,
                        0 AS totalC,
                        0 AS totalD
                    FROM cajas c;
                    """
                    self.cajasmodel.setQuery( q )
#                    FIXME:Esto no funciona en el caso de que hallan varias cajas y solo 
                    if self.cajasmodel.rowCount() == 0:
                        QMessageBox.critical( self, qApp.organizationName(),
                                         "No existe ninguna caja en la base de datos" )

                query = QSqlQuery( """
                SELECT
                    fechacreacion
                    FROM esquipulasdb.documentos d
                    LEFT JOIN personasxdocumento pd ON pd.iddocumento = d.iddocumento
                    WHERE pd.idpersona = %d AND idtipodoc =%d;
                    """ % ( self.editmodel.datosSesion.usuarioId,
                            constantes.IDARQUEO ) )
                query.first()
                self.fechaApertura = query.value( 0 ).toDate()
                
                

            except UserWarning as inst:
                QMessageBox.critical( self, qApp.organizationName(),
                                      unicode( inst ) )
                logging.error( unicode( inst ) )
            except Exception as inst:
                logging.critical( unicode( inst ) )
            finally:
                if QSqlDatabase.database().isOpen():
                    QSqlDatabase.database().close()

            self.dtFechaTime.setDisplayFormat( 'dd/MM/yyyy' )
            self.dtFechaTime.setMaximumDateTime( QDateTime.currentDateTime() )
            if self.fechaApertura is not None:
                self.dtFechaTime.setMinimumDate( self.fechaApertura )


            self.cbcaja.setModel( self.cajasmodel )
            self.cbcaja.setModelColumn( 1 )
            self.cbcaja.setCurrentIndex( -1 )
            self.dtFechaTime.setDateTime( QDateTime.currentDateTime() )

            self.buttonBox.rejected.connect( self.reject )

    def accept( self ):
        if not self.cerrar:
            self.editmodel.datosSesion.cajaId = self.cajasmodel.record( self.cbcaja.currentIndex() ).value( "idcaja" ).toInt()[0]

        if self.editmodel.valid:
            supervisor = User( self.txtUser.text(), self.txtPassword.text() )
            if supervisor.valid:
                if not supervisor.hasRole( 'gerencia' ):
                    QMessageBox.critical( self, qApp.organizationName() + u": Autenticación", "El usuario %s no tiene permisos para autorizar la apertura de caja" % supervisor.user )
                    logging.info( u"El usuario %s intento autorizar la apertura de una sesión" % supervisor.user )
                    return


                self.editmodel.supervisorId = supervisor.uid
                self.editmodel.datosSesion.fecha = self.dtFechaTime.date()

                if not self.editmodel.save():
                    QMessageBox.warning( self,
                                         qApp.organizationName(),
                                         self.editmodel.error )
                    logging.error( self.editmodel.error )
                    #else:
                        #QMessageBox.warning( None, u"La sesión no fue abierta", u"La sesión no fue abierta. Por favor Contacte al administrador del sistema")
                else:
                    QMessageBox.information( self,
                                             qApp.organizationName(),
                                              u"La sesión fue abierta exitosamente" )
                    logging.info( u"El usuario %s ha abierto una sesión de caja autorizada por el usuario %s " % ( self.parentWindow.user.user, supervisor.user ) )
                    super( DlgApertura, self ).accept()
            else:
                QMessageBox.critical( self,
                                      qApp.organizationName() + u": Autenticación",
                                      supervisor.error )
                self.txtUser.setFocus()
                self.txtPassword.setText( "" )
        else:
            self.cbcaja.setFocus()
            QMessageBox.warning( self, qApp.organizationName(),
                                  self.editmodel.error )
            #self.editmodel.errorId =0

    @pyqtSlot()
    def on_txtSaldoC_editingFinished( self ):
        if self.editmodel != None:
            self.editmodel.saldoCordoba = Decimal( str( self.txtSaldoC.value() ) )


    @pyqtSlot()
    def on_txtSaldoD_editingFinished( self ):
        if self.editmodel != None:
            self.editmodel.saldoDolar = Decimal( str( self.txtSaldoD.value() ) )
            
    @pyqtSlot(int)
    def on_cbcaja_currentIndexChanged(self,indice):
        if indice ==-1:
            self.txtSaldoC.setValue(0)
            self.txtSaldoD.setValue(0)
        else:
            self.txtSaldoC.setValue( Decimal( self.cajasmodel.data(self.cajasmodel.index(indice,2)).toString()))
            self.txtSaldoD.setValue( Decimal( self.cajasmodel.data(self.cajasmodel.index(indice,3)).toString()))
       

    @property
    def idsesion( self ):
        return self.sesion

    @property
    def fecha( self ):
        return self.dtFechaTime.date()
Ejemplo n.º 16
0
class DatosRecibo( object ):
    def __init__( self, datosSesion ):
        object.__init__( self )

        self.__documentType = 18
        self.clienteId = 0
        self.observaciones = ""
        self.aplicarRet = True

        self.lineas = []
        self.lineasAbonos = []
        self.numeroImpreso = ''

        self.conceptoId = 0
        self.datosSesion = datosSesion
        self.retencionId = 0
        self.retencionTasa = Decimal( 0 )
        self.retencionNumeroImpreso = ''


    @property
    def total( self ):
        """
        """
        tmpsubtotal = sum( [linea.monto for linea in self.lineasAbonos] )
        return tmpsubtotal if tmpsubtotal > 0 else Decimal( 0 )

    @property
    def subtotal( self ):
        """
        """
        tmpsubtotal = sum( [linea.subMonto for linea in self.lineasAbonos] )
        return tmpsubtotal if tmpsubtotal > 0 else Decimal( 0 )

    @property
    def totalPagado( self ):
        """
    
        """
        return self.total - self.obtenerRetencion




    def valid( self, recibo ):
        """
        Un documento es valido cuando 
        self.printedDocumentNumber != ""
        self.providerId !=0
        self.validLines >0
        self.__idIVA !=0
        self.uid != 0
        self.warehouseId != 0 
        """

        if int( self.clienteId ) == 0:
            try:
                recibo.cbcliente.setFocus()
            except:
                pass
            QMessageBox.information( None, "Guardar Recibo", "No existe un cliente seleccionado" )
        elif int( self.conceptoId ) == 0:
            try:
                recibo.cbconcepto.setFocus()
            except:
                pass
            QMessageBox.information( None, "Guardar Recibo", "No hay un concepto" )
        elif self.aplicarRet and int( self.retencionId ) == 0:
                recibo.cbtasaret.setFocus()
                QMessageBox.information( None, "Guardar Recibo", "No hay tasa de retencion" )
        elif self.datosSesion.tipoCambioBanco == 0:
            QMessageBox.information( None, "Guardar Recibo", "no hay un tipo de cambio para la fecha" + self.datosSesion.fecha )
        elif int( self.datosSesion.usuarioId ) == 0:
            raise Exception( "No hay un usuario" )
        elif  self.printedDocumentNumber == "":
            raise Exception( "No existe numero de doc impreso" )
        else:
            foo = 0
            for line in self.lineas:
                foo += 1
                if not line.valid:
                    recibo.tabledetails.selectRow( foo - 1 )
                    QMessageBox.information( None, "Guardar Recibo", u"La linea " + str( foo ) + u" de los pagos esta incompleta. " + line.error )
                    return False
            if len( self.lineasAbonos ) == 0:
                QMessageBox.information( None, "Guardar Recibo", u"Por favor elija al menos una factura a la que se realizará el abono" )
                return False

            foo = 0
            for line in self.lineasAbonos:
                foo += 1

                if not line.valid:
                    QMessageBox.information( None, "Guardar Recibo", u"La linea " + str( foo ) + u" de las facturas abonadas no es válida" )
                    return False


            return True
        return False

    @property
    def retencionValida( self ):
        subtotal = self.subtotal
        subtotalC = subtotal * self.datosSesion.tipoCambioBanco
        return subtotalC > 1000

    @property
    def obtenerRetencion( self ):
        if self.aplicarRet:

            if not self.retencionValida:
                self.aplicarRet = False
                self.retencionId = 0
                return Decimal( 0 )
            else:
                return ( self.subtotal * ( self.retencionTasa / Decimal( 100 ) ) )
        else:
            return Decimal( 0 )

    @property
    def obtenerGanancia( self ):
        total = self.total
        retencion = self.obtenerRetencion
        return Decimal( str( round( ( total + retencion ) * ( self.datosSesion.tipoCambioBanco - self.datosSesion.tipoCambioOficial ), 4 ) ) )

    @property
    def validLines( self ):
        """
        la cantidad de lineas validas que hay en el documento
        """
        foo = 0
        for line in self.lineas:
            if line.valid:foo += 1
        return foo

    def save( self, sinFactura = True ):
        """
        Este metodo guarda el documento actual en la base de datos
        """

        if not self.valid:
            raise Exception( "El documento a salvar no es valido" )

        query = QSqlQuery()

        try:

            if sinFactura:
                if not QSqlDatabase.database().transaction():
                    raise Exception( u"No se pudo comenzar la transacción" )

            fechaCreacion = self.datosSesion.fecha.toString( 'yyyyMMdd' ) + QDateTime.currentDateTime().toString( "hhmmss" )
    #INSERTAR RECIBO
            query.prepare( """
            INSERT INTO documentos (ndocimpreso,fechacreacion,idtipodoc, observacion,total,idtipocambio,idconcepto,idcaja) 
            VALUES ( :ndocimpreso,:fechacreacion,:idtipodoc,:observacion,:total,:idtc,:concepto,:caja)
            """ )
            query.bindValue( ":ndocimpreso", self.printedDocumentNumber )
            query.bindValue( ":fechacreacion", fechaCreacion )
            query.bindValue( ":idtipodoc", self.__documentType )
            query.bindValue( ":observacion", self.observaciones )
            totalPagado = self.totalPagado
            query.bindValue( ":total", totalPagado.to_eng_string() )

            query.bindValue( ":idtc", self.datosSesion.tipoCambioId )
            query.bindValue( ":concepto", self.conceptoId )
            query.bindValue( ":caja", self.datosSesion.cajaId )

            if not query.exec_():
                raise Exception( "No se pudo insertar el recibo" )
            insertedId = query.lastInsertId().toString()


    #INSERTAR LA RELACION CON LA SESION DE CAJA            
            query.prepare( """
                INSERT INTO docpadrehijos (idpadre,idhijo)
                VALUES (:idsesion,:idrecibo)
                """ )

            query.bindValue( ":idsesion", self.datosSesion.sesionId )
            query.bindValue( ":idrecibo", insertedId )

            if not query.exec_():
                raise Exception( "No se Inserto la relacion entre la sesion de caja y el recibo" )


    #INSERTAR LA RELACION CON El USUARIO y EL CLIENTE

            query.prepare( 
                "INSERT INTO personasxdocumento (iddocumento,idpersona,idaccion) VALUES" +
                "(" + insertedId + ",:iduser,:autor),"
                "(" + insertedId + ",:idcliente,:cliente)"
                )

            query.bindValue( ":iduser", self.datosSesion.usuarioId )
            query.bindValue( ":autor", constantes.AUTOR )
            query.bindValue( ":idcliente", self.clienteId )
            query.bindValue( ":usuario", constantes.CLIENTE )


            if not query.exec_():
                raise Exception( "No se Inserto la relacion entre el recibo y las personas" )

    #INSERTAR LOS TIPOS DE PAGO

            if len( self.lineas ) == 0:
                raise Exception( "Deben existir pagos" )

            i = 1
            for linea in self.lineas:
    #                    print insertedId + "-" + str(linea.pagoId) + "-" + str(linea.monedaId)
                linea.save( insertedId, i )
                i = i + 1
    #INSERTAR los abonos
            i = 0

            if len( self.lineasAbonos ) == 0:
                raise Exception( "Deben existir abonos" )

            for l in self.lineasAbonos:
                l.save( insertedId, i )
                i = i + 1

    #VERIFICO SI se aplicara la retencion                     
            if self.aplicarRet :

    #INSERTAR EL DOCUMENTO RETENCION CON EL TOTAL EN NEGATIVO, PORQUE ESTA SALIENDO DE CAJA            
                query.prepare( """
                INSERT INTO documentos (ndocimpreso,fechacreacion,idtipodoc,total,idtipocambio,idconcepto) 
                VALUES ( :ndocimpreso,:fechacreacion,:idtipodoc,:total,:idtc,:concepto)
                """ )
                query.bindValue( ":ndocimpreso", self.retencionNumeroImpreso )
                query.bindValue( ":fechacreacion", fechaCreacion )
                query.bindValue( ":idtipodoc", constantes.IDRETENCION )
                query.bindValue( ":total", self.obtenerRetencion.to_eng_string() )
                query.bindValue( ":idtc", self.datosSesion.tipoCambioId )
                query.bindValue( ":concepto", self.conceptoId )
                if not query.exec_():
                    raise Exception( "No se Inserto la retencion" )

                idret = query.lastInsertId().toString()

                query.prepare( "INSERT INTO docpadrehijos (idpadre,idhijo) VALUES" +
                "(:idsesion," + idret + ")," +
                "(:idrecibo," + idret + ")" )

                query.bindValue( ":idsesion", self.datosSesion.sesionId )
                query.bindValue( ":idrecibo", insertedId )

                if not query.exec_():
                    raise Exception( "No se Inserto la relacion entre la retencion y el recibo" )


    # INSERTAR EL ID DEL COSTO RETENCION                
                query.prepare( """
                INSERT INTO costosxdocumento (iddocumento, idcostoagregado) VALUES( :iddocumento, :idcostoagregado )
                """ )
                query.bindValue( ":iddocumento", insertedId )
                query.bindValue( ":idcostoagregado", self.retencionId )
                if not query.exec_():
                    raise Exception( "el costo Retencion  NO SE INSERTO" )


            #manejar las cuentas contables
            tasa = self.datosSesion.tipoCambioOficial
            movAbonoDeCliente( insertedId, self.total * tasa, self.obtenerRetencion * tasa, self.obtenerGanancia )

            if sinFactura:
                if not QSqlDatabase.database().commit():
                    raise Exception( "No se pudo hacer commit" )
        except Exception as inst:
            QSqlDatabase.database().rollback()
            return False

        return True

    def cargarRetenciones( self, cbtasaret ):
#            Rellenar el combobox de las retenciones
            self.retencionModel = QSqlQueryModel()
            self.retencionModel.setQuery( """
                    SELECT 
                        idcostoagregado, 
                        FORMAT(valorcosto,0) as tasa
                    FROM costosagregados 
                    WHERE 
                    (idtipocosto=%d OR idtipocosto =%d) AND 
                    activo=1 
                    ORDER BY valorcosto desc; 
                    """ % ( constantes.RETENCIONPROFESIONALES, constantes.RETENCIONFUENTE ) )

            cbtasaret.setModel( self.retencionModel )
            cbtasaret.setModelColumn( 1 )
            cbtasaret.setCurrentIndex( -1 )
            self.retencionId = 0

    def cargarNumeros( self, recibo ):
#            Cargar el numero de el Recibo actual
        idrec = str( constantes.IDRECIBO )
        idret = str( constantes.IDRETENCION )
        query = QSqlQuery( "CALL spConsecutivo(" + idrec + ",null)" )
        if not query.exec_():
            print( query.lastError().text() )
        query.first()
        n = query.value( 0 ).toString()

        recibo.lblnrec.setText( n )
        self.printedDocumentNumber = n

        query = QSqlQuery( "CALL spConsecutivo(" + idret + ",null)" )
        if not query.exec_():
            print( query.lastError().text() )
        query.first()
        n = query.value( 0 ).toString()
        recibo.lblnreten.setText( n )
        self.retencionNumeroImpreso = n


    def tasaRetencionCambio( self, _recibo, index ):
        self.retencionId = self.retencionModel.record( index ).value( "idcostoagregado" ).toInt()[0]
        value = self.retencionModel.record( index ).value( "tasa" ).toString()
        self.retencionTasa = Decimal( value if value != "" else 0 )
Ejemplo n.º 17
0
class dlgmovimientosbancarios (QDialog,Ui_dlgMovimientosBancarios):
    def __init__( self, parent  ):
        super( dlgmovimientosbancarios, self ).__init__( parent ) 
        self.conceptosModel = QSqlQueryModel() 
        self.setupUi( self )
        self.database = QSqlDatabase.database()
        self.proxymodel = QSortFilterProxyModel()
        self.editmodel = MovimientosBancariosModel()
        
        
        fecha = self.parent().editmodel.fechaConciliacion
        self.dtPicker.setMaximumDate(fecha)
        self.dtPicker.setMinimumDate(QDate(fecha.year(),fecha.month(),1))
        self.cbtipodoc.addItem(u"Nota de Crédito")
        self.cbtipodoc.addItem(u"Nota de Débito")
        
        self.conceptosModel.setQuery( """
               SELECT idconcepto, descripcion,idtipodoc FROM conceptos c WHERE idtipodoc in (%d,%d );
            """ %(constantes.IDNOTACREDITO,constantes.IDND) )
        
        
        self.proxymodel.setSourceModel(self.conceptosModel)
        self.proxymodel.setFilterKeyColumn(2)
        self.proxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.cbconcepto.setModel(self.proxymodel)
        self.cbconcepto.setModelColumn(1)
        self.buttonBox.rejected.connect( self.reject )
        self.buttonBox.accepted.connect( self.aceptar )
        
        self.editmodel.tipoDoc = constantes.IDDEPOSITO 

        
        self.cuentasDelegate = AccountsSelectorDelegate( QSqlQuery( """
            SELECT c.idcuenta, c.codigo, c.descripcion
            FROM cuentascontables c
            JOIN cuentasxdocumento cd ON c.idcuenta = cd.idcuenta
            WHERE c.idcuenta in (%d,%d,%d)
            """ %(constantes.CAJAGENERAL,constantes.CAJACHICA, constantes.CAPITAL) ) )


        self.editmodel.insertRow( 1 )
        self.editmodel.lines[0].itemId = parent.editmodel.idCuentaContable
        self.editmodel.lines[0].code = parent.txtcuenta.text()
        self.editmodel.lines[0].name = parent.txtcuenta.toolTip()
        

        self.editmodel.insertRow( 1 )
        self.editmodel.fechaDoc = QDateTime.currentDateTime()
        self.editmodel.autorId = parent.user.uid
            #        Crea un edit delegate para las cuentas
        self.tabledetails.setItemDelegate( self.cuentasDelegate )
        self.tabledetails.setModel( self.editmodel )
        self.tabledetails.setEditTriggers( 
                          QAbstractItemView.EditKeyPressed |
                          QAbstractItemView.AnyKeyPressed |
                          QAbstractItemView.DoubleClicked )

        self.tabledetails.setColumnHidden(0,False)
        
        
    
    @pyqtSlot( int )
    def on_cbtipodoc_currentIndexChanged(self,index):
        self.editmodel.tipoDoc = constantes.IDNOTACREDITO if self.cbtipodoc.currentIndex()== 0 else constantes.IDND
        self.proxymodel.setFilterRegExp("%d"%self.editmodel.tipoDoc)

    @pyqtSlot( int )
    def on_cbconcepto_currentIndexChanged(self,index):
        self.editmodel.conceptoId =self.conceptosModel.record( index ).value( "idconcepto" ).toInt()[0]
        
     
    def aceptar(self):
        """
    Guardar el documento actual
        """
        self.editmodel.totalDoc =    self.editmodel.lines[0].amount 
        self.editmodel.tipoDoc = constantes.IDNOTACREDITO if self.cbtipodoc.currentIndex()== 0 else constantes.IDND
        if self.editmodel.valid:
#            Base.save( self, True )
            if QMessageBox.question( self,
                                     qApp.organizationName(),
                                      u"¿Desea guardar el documento?",
                                       QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
                if self.editmodel.save():
                    QMessageBox.information( self,
                                             qApp.organizationName(),
                         u"El documento se ha guardado con éxito" )
                else:
                    QMessageBox.critical( self,
                         qApp.organizationName(),
                        "Ha ocurrido un error al guardar el documento" )
            self.accept()

            
        else:
            QMessageBox.information(None, "Datos Incompletos", self.editmodel.mensajeError)
Ejemplo n.º 18
0
class FrmOperations(QMainWindow, Ui_frmOperations):
    def __init__(self, parent=None):
        super(FrmOperations, self).__init__(parent)
        self.setupUi(self)
        self.__status = False
        self.database = QSqlDatabase.database()

        self.navmodel = QSqlQueryModel()
        self.navproxymodel = QSortFilterProxyModel()
        self.navproxymodel.setFilterKeyColumn(-1)
        self.navproxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.navproxymodel.setSourceModel(self.navmodel)

        self.detailsmodel = QSqlQueryModel()
        self.detailsproxymodel = QSortFilterProxyModel()
        self.detailsproxymodel.setSourceModel(self.detailsmodel)

        self.navproxymodel.setDynamicSortFilter(True)
        self.detailsproxymodel.setDynamicSortFilter(True)

        self.mapper = QDataWidgetMapper(self)
        self.mapper.setModel(self.navproxymodel)

        self.user = user.LoggedUser

        self.editModel = None

        self.tableNavigation.setModel(self.navproxymodel)
        self.tableDetails.setModel(self.detailsproxymodel)

        self.tableDetails.setColumnHidden(IDCUENTA, True)
        self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)

        self.actionCancelar.setVisible(False)
        self.actionGuardar.setVisible(False)

        #        self.actionGuardar.activated.connect( self.save )
        self.tableNavigation.selectionModel().selectionChanged[QItemSelection, QItemSelection].connect(
            self.updateDetails
        )

        QTimer.singleShot(0, self.updateModels)

    def updateModels(self):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo conectar con la base de datos")
            self.navmodel.setQuery(
                """
            SELECT 
                d.iddocumento, 
                d.ndocimpreso as 'N Doc', 
                d.fechacreacion as 'Fecha', 
                c.descripcion as 'Concepto'
            FROM documentos d
            JOIN conceptos c ON c.idconcepto = d.idconcepto
            WHERE d.idtipodoc = %d
            ORDER BY d.iddocumento DESC
            """
                % constantes.IDAJUSTECONTABLE
            )
            self.detailsmodel.setQuery(
                """
            SELECT 
                cxd.idcuenta,  
                cc.codigo as 'Codigo Cuenta', 
                cc.descripcion as 'Nombre Cuenta',
                CONCAT('C$',FORMAT(cxd.monto,4)) as Monto,
                cxd.iddocumento  
            FROM cuentasxdocumento cxd 
            JOIN cuentascontables cc ON cxd.idcuenta = cc.idcuenta
            JOIN documentos d ON d.iddocumento = cxd.iddocumento 
            WHERE d.idtipodoc = %d
            ORDER BY nlinea 
            """
                % constantes.IDAJUSTECONTABLE
            )

            self.mapper.addMapping(self.dtPicker, FECHACREACION)
            self.mapper.addMapping(self.txtConcept, CONCEPTO)
            self.tableNavigation.selectionModel().setCurrentIndex(
                self.navproxymodel.index(0, 0), QItemSelectionModel.Select
            )

            self.tableNavigation.setColumnHidden(IDDOCUMENTO, True)
            self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
            self.tableDetails.setColumnHidden(IDCUENTA, True)

            self.tableDetails.setColumnWidth(CODIGO, 240)
            self.tableDetails.setColumnWidth(DESCRIPCION, 250)

            self.tableNavigation.setColumnWidth(FECHACREACION, 200)
            self.tableNavigation.setColumnWidth(CONCEPTO, 250)
        except UserWarning as inst:
            logging.error(inst)
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(inst)

    def updateDetails(self, selected, _deselected):
        if len(selected.indexes()) > 0:
            self.mapper.setCurrentModelIndex(selected.indexes()[0])
            self.detailsproxymodel.setFilterKeyColumn(IDDOCUMENTOC)
            self.detailsproxymodel.setFilterRegExp(self.navproxymodel.data(selected.indexes()[0]).toString())

    def setStatus(self, status):
        """
        Cambiar el modo del formulario
        
        true = adding
        false = navigating
        
        @param status: El modo del formulario
        @type status:bool
        """

        self.widget.setHidden(status)
        self.txtSearch.setEnabled(not status)
        self.actionNuevo.setVisible(not status)
        self.actionCancelar.setVisible(status)
        self.actionGuardar.setVisible(status)
        self.cbConcepts.setEnabled(status)
        self.tableDetails.setEditTriggers(QTableView.AllEditTriggers if status else QTableView.NoEditTriggers)
        self.tableNavigation.setEnabled(not status)
        self.tableDetails.setEditTriggers(QTableView.AllEditTriggers)
        #        self.stackedWidget.setCurrentIndex( 0 if status else 1 )
        self.stConcepts.setCurrentIndex(1 if status else 0)

    def getStatus(self):
        return self.__status

    status = property(getStatus, setStatus)

    @pyqtSlot()
    def on_actionCancelar_activated(self):
        self.status = False
        self.editModel = None
        self.tableDetails.setModel(self.detailsproxymodel)
        self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
        self.tableDetails.setColumnHidden(IDCUENTA, True)

    @pyqtSlot()
    def on_actionGuardar_activated(self):
        self.save()

    @pyqtSlot()
    def on_actionNuevo_activated(self):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo abrir la base de datos")

            self.editModel = AccountsSelectorModel()
            self.editModel.insertRow(1)

            delegate = AccountsSelectorDelegate(
                QSqlQuery(
                    """
            SELECT 
                c.idcuenta, 
                c.codigo, 
                c.descripcion 
            FROM cuentascontables c 
            JOIN cuentascontables p ON c.padre = p.idcuenta AND p.padre != 1
            """
                )
            )

            self.dtPicker.setDateTime(QDateTime.currentDateTime())
            self.dtPicker.setMaximumDateTime(QDateTime.currentDateTime())

            self.conceptsmodel = QSqlQueryModel()
            q = """
            SELECT
                idconcepto,
                descripcion
            FROM conceptos
            WHERE idtipodoc = %d and idconcepto <>%d
             """ % (
                constantes.IDAJUSTECONTABLE,
                constantes.IDCONCEPTOBALANCEINICIAL,
            )

            self.conceptsmodel.setQuery(q)

            if self.conceptsmodel.rowCount() < 1:
                raise UserWarning(
                    "No existen conceptos para ajustes contables, por favor comuniquese con el administrador del sistema"
                )

            self.cbConcepts.setModel(self.conceptsmodel)
            self.cbConcepts.setModelColumn(1)
            self.tableDetails.setModel(self.editModel)
            self.tableDetails.setColumnHidden(IDCUENTA, True)
            self.tableDetails.setColumnHidden(IDDOCUMENTOC, True)
            self.tableDetails.setItemDelegate(delegate)

            self.status = True

            self.tableDetails.resizeColumnsToContents()
        except UserWarning as inst:
            self.status = False
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            logging.error(unicode(inst))
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un error al tratar de iniciar un nuevo ajuste")
            logging.critical(unicode(inst))
            self.status = False

    @pyqtSlot("QString")
    def on_txtSearch_textChanged(self, text):

        self.navproxymodel.setFilterRegExp(text)

    def save(self):
        query = QSqlQuery()

        try:
            if not self.editModel.valid:
                raise UserWarning("El documento no es valido, no se puede guardar")

            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning("No se pudo conectar con la base de datos")

            if not self.database.transaction():
                raise Exception(u"No se pudo comenzar la transacción")
            #               Cargar el numero del asiento actual
            query.prepare(
                """
            SELECT
                  MAX(CAST(ndocimpreso AS SIGNED))+1
            FROM documentos d
            WHERE idtipodoc=24
            ;
            """
            )

            query.exec_()
            query.first()

            n = query.value(0).toString()
            if n == "0":
                n = "1"

            if not query.prepare(
                """
            INSERT INTO documentos (ndocimpreso, fechacreacion, idconcepto,   idtipodoc)
            VALUES (:ndocimpreso, :fechacreacion, :idconcepto,  %d)
            """
                % constantes.IDAJUSTECONTABLE
            ):
                raise Exception("No se pudo preparar la consulta para guardar el documento")
            query.bindValue(":ndocimpreso", n)
            query.bindValue(":fechacreacion", self.dtPicker.dateTime().toString("yyyyMMddhhmmss"))
            query.bindValue(
                ":idconcepto", self.conceptsmodel.record(self.cbConcepts.currentIndex()).value("idconcepto").toInt()[0]
            )

            if not query.exec_():
                raise Exception("No se pudo ejecutar la consulta para guardar el asiento")

            insertedId = query.lastInsertId().toInt()[0]

            if not query.prepare(
                """
            INSERT INTO personasxdocumento (idpersona, iddocumento, idaccion) 
            VALUES (:usuario, :documento, :idaccion)
            """
            ):
                raise Exception("No se pudo preparar la consulta para insertar el usuario")
            query.bindValue(":usuario", self.user.uid)
            query.bindValue(":documento", insertedId)
            query.bindValue(":idaccion", constantes.ACCCREA)

            if not query.exec_():
                raise Exception(u"No se pudo guardar la relación con el usuario")

            for lineid, line in enumerate(self.editModel.lines):
                if line.valid:
                    line.save(insertedId, lineid + 1)

            if not self.database.commit():
                raise Exception("No se pudo ejecutar la transaccion")
            self.tableDetails.setModel(self.detailsproxymodel)
            self.updateModels()

            self.status = False
        except UserWarning as inst:
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
            logging.error(inst)
        except Exception as inst:
            QMessageBox.critical(self, qApp.organizationName(), "Hubo un error al tratar de guardar su ajuste")
            self.database.rollback()
            logging.critical(inst)
            logging.critical(query.lastError().text())
        finally:
            if self.database.isOpen():
                self.database.close()
Ejemplo n.º 19
0
class FrmPago( Ui_frmPago, Base ):
    """
    Implementacion de la interfaz grafica para entrada compra
    """
    web = "recibos.php?doc="

    def __init__( self , sesion, parent ):
        '''
        Constructor
        @param sesion: Los datos de la sesión actual de caja
        @param parent: La ventana padre del formulario
        @type sesion: DatosSesion
        '''
        super( FrmPago, self ).__init__( parent, True )
        self.setWindowModality( Qt.WindowModal )
        self.setWindowFlags( Qt.Dialog )
        self.sesion = sesion
        self.tabledetails = None


        self.editmodel = None

        self.groupcuentas.setVisible( False )

        self.actionSave.setVisible( False )
        self.actionCancel.setVisible( False )

#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#        El modelo principal
        self.navmodel = QSqlQueryModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = QSortFilterProxyModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++        

#        Este es el modelo con los datos de la con los detalles
        self.detailsmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )

        self.sbtotalc.setValue( 0 )
        self.sbtotald.setValue( 0 )

        self.conceptosModel = QSqlQueryModel()

        QTimer.singleShot( 0, self.loadModels )


    def cancel( self ):
        """
        Aca se cancela la edicion del documento
        """
        self.status = True


    def newDocument( self ):
        """
        activar todos los controles, llenar los modelos necesarios, 
        crear el modelo Pago, aniadir una linea a la tabla
        """
        if not self.database.isOpen():
            if not self.database.open():
                raise UserWarning( u"No se pudo establecer la conexión con "\
                                   + "la base de datos" )
        query = QSqlQuery()
        try:

#            Rellenar el combobox de las CONCEPTOS

            self.conceptosModel.setQuery( """
               SELECT idconcepto, descripcion FROM conceptos c WHERE idtipodoc = %d;
            """ % constantes.IDPAGO )

            if self.conceptosModel.rowCount() == 0:
                raise UserWarning( u"No existen conceptos en la base de "\
                                   + "datos para los pagos" )

            self.beneficiariosModel = QSqlQueryModel()
            self.beneficiariosModel.setQuery( """
            SELECT
            s.idpersona,
            s.nombre
            FROM personas s
            WHERE s.tipopersona <> %d
            ORDER BY s.nombre
            """ % constantes.AUTOR )

            if self.beneficiariosModel.rowCount() == 0:
                raise UserWarning( u"No existen personas en la base de datos" )

            #            Rellenar el combobox de las retenciones
            self.retencionModel = QSqlQueryModel()
            self.retencionModel.setQuery( """
                    SELECT 
                        idcostoagregado, 
                        FORMAT(valorcosto,0) as tasa
                    FROM costosagregados 
                    WHERE 
                    idtipocosto IN (%d,%d) AND 
                    activo=1 
                    ORDER BY valorcosto desc; 
                    """ % ( constantes.RETENCIONPROFESIONALES,
                            constantes.RETENCIONFUENTE ) )
            if self.retencionModel.rowCount() == 0:
                raise UserWarning( u"No existe ninguna tasa de retención en "\
                                   + "la base de datos" )
            query = QSqlQuery( 
            """
            SELECT
                SUM(IF(m.idtipomoneda = %d,m.monto,0)) as totalC,
                SUM(IF(m.idtipomoneda = %d,m.monto,0)) as totalD
            FROM
            movimientoscaja m
            JOIN documentos d ON d.iddocumento = m.iddocumento
            WHERE d.idcaja = %d AND m.idtipomovimiento=%d
            ;
            """ % ( constantes.IDCORDOBAS,
                    constantes.IDDOLARES,
                    self.sesion.cajaId,
                    constantes.IDPAGOEFECTIVO ) )
            if not query.exec_():
                raise UserWarning( u"No pudo obtenerse de la base de datos la cantidad de dinero en caja" )
            query.first()
            maxCordoba = Decimal( query.value( 0 ).toString() )
            maxDolar = Decimal( query.value( 1 ).toString() )

            if maxCordoba <= 0 and maxDolar <= 0:
                raise UserWarning( u"No hay Efectivo en Caja" )


            query = QSqlQuery( "SELECT fnCONSECUTIVO(%d,null);" % constantes.IDPAGO )
            if not query.exec_():
                raise UserWarning( u"No pudo obtenerse el número del comprobante" )
            query.first()
            ndoc = query.value( 0 ).toString()
            self.lblnpago.setText( ndoc )

            self.txttipocambio.setText( moneyfmt( self.sesion.tipoCambioBanco, 4 ) )

            self.cbtasaret.setModel( self.retencionModel )
            self.cbtasaret.setModelColumn( 1 )
            self.cbtasaret.setCurrentIndex( -1 )
            self.retencionId = 0



            self.cbbeneficiario.setModel( self.beneficiariosModel )
            self.cbbeneficiario.setCurrentIndex( -1 )
            self.cbbeneficiario.setModelColumn( 1 )
            completer = QCompleter()
            completer.setCaseSensitivity( Qt.CaseInsensitive )
            completer.setModel( self.beneficiariosModel )
            completer.setCompletionColumn( 1 )


            self.cbconcepto.setModel( self.conceptosModel )
            self.cbconcepto.setCurrentIndex( -1 )
            self.cbconcepto.setModelColumn( 1 )
            completerconcepto = QCompleter()
            completerconcepto.setCaseSensitivity( Qt.CaseInsensitive )
            completerconcepto.setModel( self.conceptosModel )
            completerconcepto.setCompletionColumn( 1 )

            self.editmodel = PagoModel( self.sesion )
            self.editmodel.docImpreso = ndoc

            self.editmodel.maxCordoba = maxCordoba
            self.editmodel.maxDolar = maxDolar
            self.sbtotalc.setToolTip( "Max= " + moneyfmt( maxCordoba, 4, 'C$' ) )
            self.sbtotald.setToolTip( "Max= " + moneyfmt( maxDolar, 4, 'US$' ) )
            self.sbtotalc.setMaximum( maxCordoba )
            self.sbtotald.setMaximum( maxDolar )

            query = QSqlQuery( """
            SELECT idcostoagregado, valorcosto 
            FROM costosagregados c  
            WHERE idtipocosto = %d AND activo = 1;
            """ % constantes.IVA )
            if not query.exec_():
                raise UserWarning( u"No pudo obtenerse la tasa de IVA" )
            query.first()
            self.editmodel.ivaId = query.value( 0 ).toInt()[0]
            self.editmodel.ivaTasa = Decimal( query.value( 1 ).toString() )



            self.ckiva.setToolTip( query.value( 1 ).toString() + '%' )


            self.status = False

        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
            logging.error( unicode( inst ) )
            logging.error( query.lastError().text() )
#        except Exception as inst:
#            QMessageBox.critical( self, qApp.organizationName(),
#                                   "Hubo un problema al tratar de crear"\
#                                   + " el nuevo pago" )
#            logging.critical( unicode( inst ) )
#            logging.error( query.lastError().text() )
        finally:
            if QSqlDatabase.database().isOpen():
                QSqlDatabase.database().close()

    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex() ).value( "iddocumento" ).toString()

    def save( self ):
        """
        Slot documentation goes here.
        """
        if self.valid:
            if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar el pago?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
                if not QSqlDatabase.database().isOpen():
                    QSqlDatabase.database().open()

                self.editmodel.observaciones = self.txtobservaciones.toPlainText()
                if self.editmodel.save():
                    QMessageBox.information( None,
                        self.trUtf8( qApp.organizationName() ),
                        self.trUtf8( u"""El pago se ha guardado con éxito""" ) )
                    self.editmodel = None
                    self.updateModels()
                    self.navigate( 'last' )
                    self.status = True
                else:
                    QMessageBox.critical( None,
                        self.trUtf8( qApp.organizationName() ),
                        self.trUtf8( """Ha ocurrido un error al guardar el pago""" ) )

                if QSqlDatabase.database().isOpen():
                    QSqlDatabase.database().close()

    @property
    def valid( self ):
        mensaje = "Ocurrio un Error al guardar"
        if self.editmodel.beneficiarioId == 0:
            mensaje = "Por favor elija el beneficiario"
            self.cbbeneficiario.setFocus()
        elif self.editmodel.conceptoId == 0:
            mensaje = "Por favor elija el concepto del pago"
            self.cbconcepto.setFocus()
        elif self.editmodel.totalD == 0 and self.editmodel.totalC == 0:
            mensaje = "Por favor escriba el monto del pago"
            if self.editmodel.maxCordoba > 0 :
                self.sbtotalc.setFocus()
            else:
                self.sbtotald.setFocus()
        else:
            return True

        QMessageBox.information( None, "Guardar Pago", mensaje )
        return False

    @pyqtSlot( int )
    @if_edit_model
    def on_cbbeneficiario_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.beneficiarioId = self.beneficiariosModel.record( index ).value( "idpersona" ).toInt()[0] if index != -1 else - 1
#            self.tableabonos.setEnabled( index != -1 )
#            self.frbotones.setEnabled( index != -1 )
#            self.abonoeditmodel.removeRows( 0, self.tablefacturas, self.abonoeditmodel.rowCount() )
#            self.abonoeditmodel.idbeneficiario = self.datosRecibo.beneficiarioId
#            self.updateFacturasFilter()
        self.updateLabels()

    @pyqtSlot( int )
    @if_edit_model
    def on_cbconcepto_currentIndexChanged( self, index ):
        """
        asignar la concepto al objeto self.editmodel
        """
        self.editmodel.conceptoId = self.conceptosModel.record( index ).value( "idconcepto" ).toInt()[0]

    @pyqtSlot( int )
    @if_edit_model
    def on_cbtasaret_currentIndexChanged( self, index ):
        """
        asignar la retencion al objeto self.editmodel
        """

        self.editmodel.retencionId = self.retencionModel.record( index ).value( "idcostoagregado" ).toInt()[0]
        value = self.retencionModel.record( index ).value( "tasa" ).toString()
        self.editmodel.retencionTasa = Decimal( value if value != "" else 0 )
        self.updateLabels()

# MANEJO EL EVENTO  DE SELECCION EN EL RADIOBUTTON
    @pyqtSlot( bool )
    @if_edit_model
    def on_ckretener_toggled( self, on ):
        """
        """
        self.editmodel.aplicarRet = on
        self.cbtasaret.setEnabled( on )
        self.cbtasaret.setCurrentIndex( -1 )

    @pyqtSlot( bool )
    @if_edit_model
    def on_ckiva_toggled( self, on ):
        """
        """
        self.editmodel.aplicarIva = on
        self.updateLabels()


    @pyqtSlot( QDateTime )
    def on_dtPicker_dateTimeChanged( self, datetime ):
        pass

    @pyqtSlot( float )
    @if_edit_model
    def on_sbtotalc_valueChanged ( self, value ):
        self.editmodel.totalC = Decimal( str( value ) )
        self.updateLabels()

    @pyqtSlot( float )
    @if_edit_model
    def on_sbtotald_valueChanged ( self, value ):
        self.editmodel.totalD = Decimal( str( value ) )
        self.updateLabels()

    def setControls( self, status ):
        """
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible( status )
        self.dtPicker.setReadOnly( True )
#        self.ckretener.setEnabled( ( not status ) )
        self.txtobservaciones.setReadOnly( status )
        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )
        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionPreview.setVisible( status )


        self.ckretener.setEnabled( False )
        self.ckiva.setEnabled( not status )

        self.sbtotalc.setReadOnly( status )
        self.sbtotald.setReadOnly( status )

#        self.txtretencion.setReadOnly(status)

        if status:
            self.editmodel = None
#            self.frbotones.setVisible( False )
            self.tablenavigation.setModel( self.navproxymodel )
#            self.tabledetails.setModel( self.detailsproxymodel )
#            self.tableabonos.setModel( self.abonosproxymodel )

#            self.tabledetails.setColumnHidden( IDPAGO, True )
#            self.tabledetails.setColumnHidden( IDMONEDA, True )
#            self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )
#            
            self.swbeneficiario.setCurrentIndex( 1 )
            self.swconcepto.setCurrentIndex( 1 )
            self.swtasaret.setCurrentIndex( 1 )
#            self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers )
#            self.tableabonos.setEditTriggers( QAbstractItemView.NoEditTriggers )
        else:
            self.tabWidget.setCurrentIndex( 0 )
            self.dtPicker.setDate( self.sesion.fecha )
            self.cbbeneficiario.setCurrentIndex( -1 )
            self.swbeneficiario.setCurrentIndex( 0 )
            self.swconcepto.setCurrentIndex( 0 )
            self.swtasaret.setCurrentIndex( 0 )
            self.txtobservaciones.setPlainText( "" )
            self.sbtotalc.setValue( 0 )
            self.sbtotald.setValue( 0 )
            self.lbltotal.setText( "US$ 0.0000" )
            self.lblretencion.setText( "US$ 0.0000" )
            self.lbltotalpago.setText( "US$ 0.0000" )

            self.cbbeneficiario.setFocus()
            self.ckretener.setChecked( False )
#            self.tabledetails.setEditTriggers( QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked )
#            self.tableabonos.setEditTriggers( QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked )


#        self.tableabonos.setColumnHidden(IDDOCUMENTO,True)
#        
#        self.tabledetails.setColumnWidth(DESCRIPCION,250)
#        self.tabledetails.setColumnWidth(MONTO,150)
#        self.tabledetails.setColumnWidth(MONTODOLAR,150)
#        self.tabledetails.setColumnWidth(REFERENCIA,150)
#    

    def updateDetailFilter( self, index ):
        record = self.navmodel.record( index )
        self.dtPicker.setDate( 
                      QDate.fromString( 
                               record.value( "Fecha" ).toString(),
                               "dd/MM/yyyy" ) )
        valor = Decimal( record.value( "totalc" ).toString() )
        self.sbtotalc.setMaximum( valor )
        self.sbtotalc.setValue( valor )

        valor = Decimal( record.value( "totald" ).toString() )
        self.sbtotald.setMaximum( valor )
        self.sbtotald.setValue( valor )

        self.tablenavigation.selectRow( self.mapper.currentIndex() )


    def updateLabels( self ):
        """
        """
        self.ckretener.setEnabled( self.editmodel.tieneRetencion )
        retencion = self.editmodel.retencionCordoba
        self.lblretencion.setText( moneyfmt( retencion / self.sesion.tipoCambioBanco, 4, "US$ " ) )
        self.lblretencion.setToolTip( moneyfmt( retencion, 4, "C$ " ) )


        self.lbltotal.setText( moneyfmt( self.editmodel.totalDolar, 4, "US$ " ) )
        self.lbltotal.setToolTip( moneyfmt( self.editmodel.totalCordoba, 4, "C$ " ) )

        total = self.editmodel.totalCordoba - retencion
        self.lbltotalpago.setText( moneyfmt( total / self.sesion.tipoCambioBanco , 4, "US$ " ) )
        self.lbltotalpago.setToolTip( moneyfmt( total, 4, "C$ " ) )


    def updateModels( self ):
        """
        Recargar todos los modelos
        """
        try:

            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo conectar con la base de datos" )

            query = """
            SELECT
                pago.iddocumento,
                pago.ndocimpreso  as 'No. Comprobante',
               pago.Fecha,
                pago.nombre as Beneficiario,
                pago.Concepto,
                CONCAT('US$',FORMAT(pago.total,4)),
                IF(SUM(IF(ca.idtipocosto=1,1,0))>0,1,0) as coniva,
                IF(SUM(IF(ca.idtipocosto in (8,9),1,0))>0,1,0) as conret,
                SUM(IF(ca.idtipocosto in (8,9),ca.valorcosto,0)) as tasaret,
                SUM(IF(mc.idtipomoneda =1,-mc.monto,0)) as totalc,
                SUM(IF(mc.idtipomoneda =2,-mc.monto,0)) as totald,
                CONCAT('US$',FORMAT(ROUND(pago.total + (pago.total / (1 +SUM(IF(ca.idtipocosto=1,ca.valorcosto/100,0))) ) * SUM(IF(ca.idtipocosto in (8,9),ca.valorcosto/100,0)),4),4)) as total,
                -- pago.total / (1 +SUM(IF(ca.idtipocosto=1,ca.valorcosto/100,0))) as subtotal,
                CONCAT('US$',FORMAT(ROUND((pago.total / (1 +SUM(IF(ca.idtipocosto=1,ca.valorcosto/100,0))) ) * SUM(IF(ca.idtipocosto in (8,9),ca.valorcosto/100,0)),4),4)) as retencion,
                pago.observacion,
                pago.tasa

                FROM costosagregados ca
                JOIN costosxdocumento cxd ON ca.idcostoagregado = cxd.idcostoagregado
                JOIN movimientoscaja mc ON mc.iddocumento = cxd.iddocumento
                JOIN
                (
                SELECT
                d.iddocumento,
                d.ndocimpreso,
                GROUP_CONCAT(IF(pxd.idaccion=2,p.nombre,'') SEPARATOR '') as nombre,
                DATE_FORMAT(d.fechacreacion,'%d/%m/%Y') AS fecha,
                d.observacion,
                con.descripcion as concepto,
                tc.tasa,
                d.total
                FROM documentos d
                JOIN conceptos con ON con.idconcepto = d.idconcepto
                JOIN personasxdocumento pxd ON pxd.iddocumento = d.iddocumento
                JOIN personas p ON p.idpersona = pxd.idpersona
                JOIN tiposcambio tc ON tc.idtc=d.idtipocambio
                WHERE d.idtipodoc=30
                GROUP BY d.iddocumento
                ) pago on pago.iddocumento = cxd.iddocumento
                GROUP BY pago.iddocumento
                ; """ # % ( constantes.IDCORDOBAS, constantes.IDDOLARES, constantes.IVA, constantes.IVA, constantes.RETENCIONFUENTE, constantes.RETENCIONPROFESIONALES, constantes.PROVEEDOR, '%d/%m/%Y', constantes.IDPAGO )

            self.navmodel.setQuery( query )

            self.navproxymodel = QSortFilterProxyModel( self )
            self.navproxymodel.setSourceModel( self.navmodel )
            self.navproxymodel.setFilterKeyColumn( -1 )
            self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )

    #        Este es el modelo con los datos de la tabla para navegar
#FIXME: Se el simbolo de la moneda deberia de salir desde la tabla tiposmoneda    
            self.detailsmodel.setQuery( """
                SELECT
                p.iddocumento,
                CONCAT(tp.descripcion, ' ' , tm.moneda) as 'Tipo de Pago',
                 p.refexterna as 'No. Referencia',
                 b.descripcion as Banco,
                 CONCAT(tm.simbolo,' ',FORMAT(monto,4)) as 'Monto',
                 CONCAT('US$ ',FORMAT(monto / IF(p.idtipomoneda=2,1,IFNULL(tc.tasaBanco,tc.tasa)),4)) as 'Monto US$'
            FROM movimientoscaja p
            JOIN documentos d ON d.iddocumento=p.iddocumento AND d.idtipodoc=18
            JOIN tiposcambio tc ON tc.idtc=d.idtipocambio
            JOIN tiposmoneda tm ON tm.idtipomoneda=p.idtipomoneda
            JOIN tiposmovimientocaja tp ON tp.idtipomovimiento=p.idtipomovimiento
            LEFT JOIN bancos b ON b.idbanco = p.idbanco
            ORDER BY p.nlinea
            ;
            """ )

    #        Este es el filtro del modelo anterior
            self.detailsproxymodel = QSortFilterProxyModel( self )
            self.detailsproxymodel.setSourceModel( self.detailsmodel )
            self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTO )
            self.detailsproxymodel.setFilterRegExp( '^0$' )
# ESTE ES EL MODELO CON LOS DATOS DE Los ABONOS PARA NAVEGAR
            self.abonosmodel = QSqlQueryModel( self )
            self.abonosmodel.setQuery( """
           SELECT
            d.idhijo as idrecibo,
            padre.ndocimpreso as 'No. Factura',
            CONCAT('US$ ',FORMAT(d.monto,4)) as 'Saldo'
            FROM docpadrehijos d
            JOIN documentos padre ON d.idpadre=padre.iddocumento
            WHERE padre.idtipodoc=%d and d.monto is not null
            ORDER BY d.nlinea
;
            """ % constantes.IDFACTURA )

    #        Este es el filtro del modelo anterior
#            self.abonosproxymodel.setSourceModel( self.abonosmodel )


    #        Este objeto mapea una fila del modelo self.navproxymodel a los controles
            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )
            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.lblnpago, NDOCIMPRESO , "text" )
#            self.mapper.addMapping( self.txtretencion, NRETENCION , "text" )

            self.mapper.addMapping( self.txtobservaciones, OBSERVACION )
#            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.txtbeneficiario, NOMBREBENEFICIARIO, "text" )
            self.mapper.addMapping( self.txtconcepto, CONCEPTO, "text" )
            self.mapper.addMapping( self.txttasaret, TASARETENCION, "text" )
            self.mapper.addMapping( self.lbltotalpago, TOTALPAGADO, "text" )
            self.mapper.addMapping( self.lbltotal, TOTAL, "text" )
            self.mapper.addMapping( self.lblretencion, TOTALRETENCION, "text" )
            self.mapper.addMapping( self.ckretener, CONRETENCION, "checked" )
            self.mapper.addMapping( self.ckiva, CONIVA, "checked" )
#            self.mapper.addMapping( self.sbtotalc, TOTALC, "value" )

            self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
            self.tablenavigation.setColumnHidden( TOTALRETENCION, True )
            self.tablenavigation.setColumnHidden( CONRETENCION, True )
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                   unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                            u"Hubo un error al tratar de obtener los datos" )
        finally:
            if self.database.isOpen():
                self.database.close()
Ejemplo n.º 20
0
class ChooseMTModelDialog(QDialog, Ui_Dialog):
    """
    Class documentation goes here.
    """
    def __init__(self, parent=None, datamodel=None):
        """
        Constructor
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.model = QSqlQueryModel()
        self.selTableView.setModel(self.model)
        self.database = datamodel.getQSqlDatabase()
        self.updateModel()
        self.selTableView.hideColumn(0)
        self.selTableView.hideColumn(5)
        self.selTableView.hideColumn(6)
        # Change status and keep the column.
        QObject.connect(
            datamodel,  SIGNAL("modelInstalled()"),
            self.on_datamodel_modelInstalled)

    def updateModel(self):
        self.model.setQuery(
            'SELECT ID, name, srclang, trglang, status, path, mosesini '
            'FROM models '
            'WHERE status = "READY" AND deleted != "True"',
            self.database)

    def on_datamodel_recordUpdated(self,  bRecord):
        """Deal with the selection changed problem."""
        try:
            if bRecord:
                current = self.selTableView.currentIndex()
                if current and current.row() != -1:
                    self.curSelection = current.row()
                else:
                    self.curSelection = None
            else:
                if self.curSelection is not None:
                    self.selTableView.selectRow(self.curSelection)
        except Exception as e:
            print >> sys.stderr, str(e)

    def on_datamodel_modelInstalled(self):
        self.updateModel()

    @pyqtSignature("")
    def on_buttonBox_accepted(self):
        """
        Slot documentation goes here.
        """
        current = self.selTableView.currentIndex()
        if not current:
            doAlert("Please choose a model to start.")
            return
        record = self.model.record(current.row())
        self.ID = record.value("ID").toString()
        self.modelName = record.value("name").toString()
        self.srcLang = record.value('srclang').toString()
        self.trgLang = record.value('trglang').toString()
        self.path = record.value("path").toString()
        self.mosesini = record.value("mosesini").toString()
        self.accept()
Ejemplo n.º 21
0
class FrmFactura( Base, Ui_frmFactura ):
    """
    Implementacion de la interfaz grafica para facturas
    """
    web = "facturas.php?doc="
    def __init__( self, parent ):
        '''
        Constructor
        '''
        super( FrmFactura, self ).__init__( parent )
        self.readOnly = True
        self.recibo = None

        self.clientesModel = QSqlQueryModel()

#       las acciones deberian de estar ocultas
        self.actionSave.setVisible( False )
        self.actionCancel.setVisible( False )
#        El modelo principal
        self.navmodel = QSqlQueryModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = QSortFilterProxyModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
        self.navproxymodel.setFilterKeyColumn( -1 )
        self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )
#        Este es el modelo con los datos de la con los detalles
        self.detailsmodel = QSqlQueryModel( self )
        self.detailsproxymodel = QSortFilterProxyModel( self )
        self.detailsproxymodel.setSourceModel( self.detailsmodel )
        #inicializando el documento
        self.editmodel = None
        self.lblanulado.setHidden( True )
        self.toolBar.removeAction( self.actionAnular )
        self.toolBar.addAction( self.actionAnular )
        self.recibo = None

        self.cargarRecibos()

        self.existenciaModel = QSqlQueryModel()
        self.vendedoresModel = QSqlQueryModel()
        self.bodegasModel = QSqlQueryModel()

        self.anulable = 2
        """
        @ivar: Si la factura actual se puede anular o no
        @type: int
        """

        self.tabledetails.setOrder( 1, 3 )

        self.completer = QCompleter()
        self.completerVendedor = QCompleter()

        QTimer.singleShot( 0, self.loadModels )

    def cargarRecibos( self ):
        self.recibo = FrmRecibo( self )  #dlgRecibo( self, True )
        self.recibo.setWindowModality( Qt.WindowModal )
        self.recibo.setWindowFlags( Qt.Dialog )
        self.recibo.actionNew.setVisible( False )

    def cancel( self ):
        """
        Aca se cancela la edición del documento
        """
        self.editmodel = None
        self.tablenavigation.setModel( self.navproxymodel )
        self.tabledetails.setModel( self.detailsproxymodel )

        self.readOnly = True
        self.status = True



    def newDocument( self ):
        """
        activar todos los controles, llenar los modelos necesarios, 
        crear el modelo FacturaModel, aniadir una linea a la tabla
        """
        self.readOnly = False



        if not self.updateEditModels():
            return

        self.status = False
        self.dtPicker.setDate( self.parentWindow.datosSesion.fecha )

    def updateEditModels( self ):
        """
        Este metodo actualiza los modelos usados en el modo edición
        """
        resultado = False
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo abrir la conexión "\
                                       + "con la base de datos" )

            self.editmodel = FacturaModel( self.parentWindow.datosSesion )

                #           Cargar el numero de la factura actual
            query = QSqlQuery( """
                        SELECT fnConsecutivo(%d,NULL);
                    """ % constantes.IDFACTURA )
            if not query.exec_():
                raise Exception( "No se pudo obtener el numero de la factura" )
            query.first()
            n = query.value( 0 ).toString()



            self.editmodel.printedDocumentNumber = n

            self.clientesModel.setQuery( """
                        SELECT idpersona , nombre AS cliente 
                        FROM personas
                        WHERE tipopersona = %d
                    """ % constantes.CLIENTE )
            if self.clientesModel.rowCount() == 0:
                raise UserWarning( "No existen clientes en la"\
                                          + " base de datos" )
                return

    #            Rellenar el combobox de los vendedores

            self.vendedoresModel.setQuery( """
                SELECT 
                idpersona, 
                nombre AS Vendedor 
                FROM personas
                WHERE tipopersona = %d
            """ % constantes.VENDEDOR )

    #Verificar si existen clientes            
            if self.vendedoresModel.rowCount() == 0:
                raise UserWarning( "No existen vendedores en la "\
                                      + "base de datos" )

        #Crear el delegado con los articulo y verificar si existen articulos
            self.existenciaModel.setQuery( QSqlQuery( """
            SELECT
                idarticulo,
                descripcion,
                precio,
                ROUND(costo,4) as costo,
                Existencia,
                idbodega
            FROM vw_articulosenbodegas
             WHERE existencia >0
                    """ ) )
            self.proxyexistenciaModel = SingleSelectionModel()
            self.proxyexistenciaModel.setSourceModel( self.existenciaModel )
            self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX )

            if self.proxyexistenciaModel.rowCount() == 0:
                raise UserWarning( "No hay articulos en bodega" )

            delegate = FacturaDelegate( self.proxyexistenciaModel )


    #            Rellenar el combobox de las BODEGAS

            self.bodegasModel.setQuery( """
                     SELECT
                            b.idbodega,
                            b.nombrebodega as Bodega
                    FROM bodegas b
                    JOIN documentos d ON b.idbodega=d.idbodega
                    JOIN docpadrehijos ph ON ph.idpadre =d.iddocumento
                    JOIN documentos k ON ph.idhijo = k.iddocumento AND k.idtipodoc = %d
            JOIN articulosxdocumento ad ON ad.iddocumento=d.iddocumento
            GROUP BY b.idbodega
            HAVING SUM(ad.unidades)>0    
                    """ % constantes.IDKARDEX )

        #Verificar si existen bodegas            
            if self.bodegasModel.rowCount() == 0:
                raise UserWarning( "No existe ninguna bodega "\
                                   + "en la base de datos" )

    #Verificar IVA    
            query = QSqlQuery( """
                    SELECT idcostoagregado, valorcosto 
                    FROM costosagregados c 
                    WHERE idtipocosto = 1 AND activo = 1 
                    ORDER BY idtipocosto;
                    """ )
            query.exec_()
            if not query.size() == 1:
                raise UserWarning( "No fue posible obtener el "\
                                   + "porcentaje del IVA" )


            query.first()


            self.editmodel.ivaId = query.value( 0 ).toInt()[0]
            self.lbltasaiva.setText( ( '0' if self.editmodel.bodegaId != 1 else str( self.editmodel.ivaTasa ) ) + '%' )
            self.editmodel.ivaTasa = Decimal( query.value( 1 ).toString() )


            self.tabledetails.setItemDelegate( delegate )


            self.cbcliente.setModel( self.clientesModel )
            self.cbcliente.setCurrentIndex( -1 )
            self.cbcliente.setFocus()
            self.cbcliente.setModelColumn( 1 )

            self.completer.setCaseSensitivity( Qt.CaseInsensitive )
            self.completer.setModel( self.clientesModel )
            self.completer.setCompletionColumn( 1 )
            self.cbcliente.setCompleter( self.completer )


            self.cbbodega.setModel( self.bodegasModel )
            self.cbbodega.setCurrentIndex( -1 )
            self.cbbodega.setModelColumn( 1 )
            self.completerbodega = QCompleter()
            self.completerbodega.setCaseSensitivity( Qt.CaseInsensitive )
            self.completerbodega.setModel( self.bodegasModel )
            self.completerbodega.setCompletionColumn( 1 )
            self.cbbodega.setCompleter( self.completerbodega )

            self.cbvendedor.setModel( self.vendedoresModel )
            self.cbvendedor.setCurrentIndex( -1 )
            self.cbvendedor.setModelColumn( 1 )

            self.completerVendedor.setCaseSensitivity( Qt.CaseInsensitive )
            self.completerVendedor.setModel( self.vendedoresModel )
            self.completerVendedor.setCompletionColumn( 1 )
            self.cbvendedor.setCompleter( self.completerVendedor )

            self.tabledetails.setModel( self.editmodel )
            self.addLine()
            self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )

            self.rbcontado.setChecked( True )
            self.txtobservaciones.setPlainText( "" )

            resultado = True
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        finally:
            if self.database.isOpen():
                self.database.close()
        return resultado

    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex()
                                     ).value( "iddocumento" ).toString()

    def addActionsToToolBar( self ):
        self.actionRefresh = self.createAction( text = "Actualizar",
                                icon = QIcon.fromTheme( 'view-refresh', QIcon( ":/icons/res/view-refresh.png" ) ),
                                 slot = self.refresh,
                                 shortcut = Qt.Key_F5 )

        self.toolBar.addActions( [
            self.actionNew,
            self.actionRefresh,
            self.actionPreview,
            self.actionPrint,
            self.actionSave,
            self.actionCancel,
        ] )
        self.toolBar.addSeparator()
        self.toolBar.addActions( [
            self.actionGoFirst,
            self.actionGoPrevious,
            self.actionGoLast,
            self.actionGoNext,
            self.actionGoLast
        ] )

    def refresh( self ):
        """
        Actualizar los modelos de edición
        """
        if not self.status:
            if QMessageBox.question( self, qApp.organizationName(),
                                      u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No:
                return
            self.updateEditModels()
        else:
            if self.updateModels():
                QMessageBox.information( None, "Factura",
                                     u"Los datos fueron actualizados con éxito" )


    def save( self ):
        """
        Guardar el documento actual
        @rtype: bool
        """
        result = False
        try:
            if not self.valid:
                return False

            if self.editmodel.escontado:
                recibo = DlgRecibo( self )
                if recibo.datosRecibo.retencionValida:
                    if recibo.datosRecibo.retencionModel.rowCount() == 0:
                        raise UserWarning( "No es posible crear un recibo "\
                        + "porque no existen retenciones en la base de datos" )
                else:
                    recibo.ckretener.setChecked( False )
                    recibo.ckretener.setEnabled( False )


                if recibo.exec_() == QDialog.Rejected:

                    return
            else:
                credito = DlgCredito( self )
                if not credito.exec_() == QDialog.Accepted:
                    return

                self.editmodel.fechaTope = credito.dtFechaTope.date()
                self.editmodel.multa = Decimal( str( credito.sbTaxRate.value() ) )

            if QMessageBox.question( self, qApp.organizationName(),
                                     u"¿Esta seguro que desea guardar la factura?",
                                     QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:

                if not self.database.isOpen():
                    if not self.database.open():
                        raise UserWarning( u"No se pudo conectar con la base de datos" )

                self.editmodel.observaciones = self.txtobservaciones.toPlainText()
                if self.editmodel.escontado:
                    recibo.datosRecibo.observaciones = recibo.txtobservaciones.toPlainText()
                if not self.editmodel.save( recibo.datosRecibo if self.editmodel.escontado else None ):
                    raise UserWarning( "No se ha podido guardar la factura" )

                QMessageBox.information( None,
                     qApp.organizationName() ,
                     u"""El documento se ha guardado con éxito""" )

                self.editmodel = None
                self.readOnly = True

                self.updateModels()
                self.cargarRecibos()
                self.navigate( 'last' )
                self.status = True
                result = True
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                 u"Hubo un error al guardar la factura" )
        finally:
            if self.database.isOpen():
                self.database.close()
        return result


#FIXME: Hay demasiados if y cosas por el estilo en esta función...deberia de 
#hacerse un refactor
    @pyqtSlot()
    def on_actionAnular_activated( self ):
        if self.anulable == 2:
            QMessageBox.warning( self, qApp.organizationName(),
                                  u"La factura no puede anularse. Solo las"\
                                  + " facturas confirmadas o en proceso de "\
                                  + "autorización pueden anularse" )
        elif self.anulable == 3:
            QMessageBox.warning( self, qApp.organizationName(),
                                  u"La factura no puede anularse porque no "\
                                  + "es del día de hoy" )
        elif self.anulable == 4:
            QMessageBox.warning( self, qApp.organizationName(),
                                  u"La factura no puede anularse porque tiene"\
                                  + " abonos" )
        elif self.anulable == 5:
            QMessageBox.warning( self, qApp.organizationName(),
                                  u"La factura no puede anularse porque tiene"\
                                  + " devoluciones" )
        elif self.anulable == 1:
            currentIndex = self.mapper.currentIndex()
            record = self.navmodel.record( currentIndex )
            doc = record.value( "iddocumento" ).toInt()[0]
            estado = record.value( "idestado" ).toInt()[0]
            total = record.value( "totalfac" ).toString()
            bodega = record.value( IDBODEGA ).toInt()[0]
            if total != "":
                total = Decimal( total )

            query = QSqlQuery()
            try:
                if not self.database.isOpen():
                    if not self.database.open():
                        raise Exception( "NO se pudo abrir la Base de datos" )

                if estado == 3:
                    if QMessageBox.question( self, qApp.organizationName(),
                                              u"Esta factura no fue confirmada,"\
                                              + " ¿Desea eliminarla?",
                                              QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
                        query = QSqlQuery()
                        query.prepare( "CALL spEliminarFactura(:doc)" )
                        query.bindValue( ":doc", doc )
                        if not query.exec_():
                            raise Exception( "No se pudo eliminar el la factura" )

                        QMessageBox.information( self, qApp.organizationName(),
                                                  "La factura fue eliminada correctamente" )
                        self.updateModels()
                else:
                    if QMessageBox.question( self, qApp.organizationName(),
                                             u"¿Esta seguro que desea anular la factura?",
                                              QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:

                        nfac = self.navmodel.record( self.mapper.currentIndex() ).value( "No. Factura" ).toString()
                        anulardialog = DlgAnular( nfac )
                        if anulardialog.conceptosmodel.rowCount() == 0:
                            QMessageBox.warning( self, qApp.organizationName(),
                                                  u"No existen conceptos para la anulación" )

                        else:
                            if anulardialog.exec_() == QDialog.Accepted:
                                if anulardialog.cboConceptos.currentIndex() == -1 and anulardialog.txtObservaciones.toPlainText() == "":
                                    QMessageBox.critical( self, qApp.organizationName(), "No ingreso los datos correctos", QMessageBox.Ok )
                                else:


                                    if not self.database.transaction():
                                        raise Exception( "No se pudo comenzar la transacción" )

                                    #Cambiar estado Anulado=1 para documento
                                    query.prepare( "UPDATE documentos d SET idestado=%d where iddocumento=%d LIMIT 1" % ( constantes.ANULACIONPENDIENTE, doc ) )
                                    if not query.exec_():
                                        raise Exception( "No se logro cambiar el estado a el documento" )

                                    #Insertar documento anulacion
                                    if not query.prepare( """
                                    INSERT INTO documentos(ndocimpreso,total,fechacreacion,idtipodoc,observacion,idestado, idbodega)
                                    VALUES(:ndocimpreso,:total,NOW(),:idtipodoc,:observacion,:idestado, :idbodega)""" ):
                                        raise Exception( query.lastError().text() )
                                    query.bindValue( ":ndocimpreso", nfac )
                                    query.bindValue( ":total", str( total ) )
#                                    query.bindValue( ":fechacreacion", QDateTime.currentDateTime().toString('yyyyMMddhhmmss') )
                                    query.bindValue( ":idtipodoc", constantes.IDANULACION )
                                    query.bindValue( ":observacion", anulardialog.txtObservaciones.toPlainText() )
                                    query.bindValue( ":idestado", constantes.PENDIENTE )
                                    query.bindValue( ":idbodega", bodega )

                                    if not query.exec_():
                                        raise Exception( "No se pudo insertar el documento Anulacion" )

                                    insertedId = query.lastInsertId().toString()

                                    if not query.prepare( "INSERT INTO docpadrehijos (idpadre,idhijo) VALUES" +
                                "(:idfac," + insertedId + ")" ):
    #                                "(:usuario," + insertedId + ",0),"
    #                                "(:supervisor," + insertedId + ",1)"):
                                        raise Exception( query.lastError().text() + "No se preparo la relacion de la anulacion con la factura" )

                                    query.bindValue( ":idfac", doc )

                                    if not query.exec_():
                                        raise Exception( "No se pudo insertar la relacion de la Anulacion con la factura" )


                                    if not query.prepare( "INSERT INTO personasxdocumento (idpersona,iddocumento,idaccion) VALUES" \
                                    + "(:usuario," + insertedId + ",:accion)" ):
                                        raise Exception( "No se inserto el usuario y autoriza" )

                                    query.bindValue( ":usuario", self.parentWindow.datosSesion.usuarioId )
                                    query.bindValue ( ":accion", constantes.AUTOR )

                                    if not query.exec_():
                                        raise Exception( "No se pudo Insertar la relacion de la anulacion con el usuario" )


                                    if not self.database.commit():
                                        raise Exception( "No se hizo el commit para la Anulacion" )

                                    QMessageBox.information( self,
                                                             qApp.organizationName(),
                                                             "Factura anulada Correctamente",
                                                             QMessageBox.Ok )
                                    self.updateModels()

            except Exception as inst:
                logging.error( unicode( inst ) )
                logging.error( query.lastError().text() )
                QMessageBox.critical( self, qApp.organizationName(),
                                      unicode( inst ) )
                self.database.rollback()
            except Exception as inst:
                logging.critical( unicode( inst ) )
                logging.critical( query.lastError().text() )
                QMessageBox.critical( self,
                                      qApp.organizationName(),
                                       "Hubo un error al intentar anular "\
                                       + "la factura" )
                self.database.rollback()
            finally:
                if self.database.isOpen():
                    self.database.close()

    @pyqtSlot()
    def on_actionRecibo_activated( self ):
        index = self.mapper.currentIndex()
        record = self.navmodel.record( index )
        self.recibo.remoteProxyModel.setFilterRegExp( "(%s)" % record.value( "iddocumento" ).toString() )
        if self.recibo.remoteProxyModel.rowCount() > 0:
            self.recibo.mapper.setCurrentIndex( 1 )
        if self.recibo.remoteProxyModel.rowCount() != 0:
            self.recibo.mapper.setCurrentIndex( 0 )
            self.recibo.show()


    @pyqtSlot( int )
    def on_cboFiltro_currentIndexChanged( self, index ):
        """
        asignar la bodega al objeto self.editmodel

        """
        self.navproxymodel.setFilterKeyColumn( ANULADO )
        if index == 0:
            self.navproxymodel.setFilterRegExp( "" )
        else:
            self.navproxymodel.setFilterRegExp( "^%d$" % index )

    @pyqtSlot( int )
    @if_edit_model
    def on_cbbodega_currentIndexChanged( self, index ):
        """
        asignar la bodega al objeto self.editmodel
        """
        if self.editmodel.rowCount() > 0 and self.editmodel.lines[0].itemDescription != "":
            self.editmodel.removeRows( 0, self.editmodel.rowCount() )

        self.editmodel.bodegaId = self.bodegasModel.record( index ).value( "idbodega" ).toInt()[0]
        self.proxyexistenciaModel.setFilterRegExp( '^%d$' % self.editmodel.bodegaId )
        self.tabledetails.setColumnHidden( IDARTICULO, True )
        self.updateLabels()



    @pyqtSlot( int )
    @if_edit_model
    def on_cbcliente_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.clienteId = self.clientesModel.record( index ).value( "idpersona" ).toInt()[0]

    @pyqtSlot( int )
    @if_edit_model
    def on_cbvendedor_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.vendedorId = self.vendedoresModel.record( index ).value( "idpersona" ).toInt()[0]


    @pyqtSlot( QDateTime )
    def on_dtPicker_dateTimeChanged( self, datetime ):
        pass

    @pyqtSlot( bool )
    @if_edit_model
    def on_rbcontado_toggled( self, on ):
        """
        Asignar las observaciones al objeto editmodel
        """
        self.editmodel.escontado = 1 if on else 0


    def setControls( self, status ):
        """
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible( status )
        self.readOnly = status
        self.txtobservaciones.setReadOnly( status )
        self.rbcontado.setEnabled( ( not status ) )
        self.rbcredito.setEnabled( not status )

        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )
        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionPreview.setVisible( status )
        self.actionAnular.setVisible( status )
        self.actionRecibo.setVisible( status )

        if status:
            self.navigate( 'last' )
            self.swcliente.setCurrentIndex( 1 )
            self.swbodega.setCurrentIndex( 1 )
            self.swvendedor.setCurrentIndex( 1 )
            self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers )

            self.tabledetails.removeAction( self.actionDeleteRow )

            self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
            self.tablenavigation.setColumnHidden( OBSERVACION, True )
            self.tablenavigation.setColumnHidden( SUBTOTAL, True )
            self.tablenavigation.setColumnHidden( IVA, True )
            self.tablenavigation.setColumnHidden( TASAIVA, True )
            self.tablenavigation.setColumnHidden( TASA, True )
            self.tablenavigation.setColumnHidden( ESCONTADO, True )
            self.tablenavigation.setColumnHidden( ANULADO, True )
            self.tablenavigation.setColumnHidden( TOTALFAC, True )
            self.tablenavigation.setColumnHidden( IDBODEGA, True )
            self.tablenavigation.setColumnHidden( ANULABLE, True )


        else:
#            self.btnrecibo.setHidden( True )
            self.tabWidget.setCurrentIndex( 0 )
            self.lblnfac.setText( self.editmodel.printedDocumentNumber )
            self.swcliente.setCurrentIndex( 0 )
            self.swbodega.setCurrentIndex( 0 )
            self.swvendedor.setCurrentIndex( 0 )
            self.lblsubtotal.setText( "0.0000" )
            self.lbliva.setText( "0.0000" )
            self.lbltotal.setText( "0.0000" )
            self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers )
            self.lblanulado.setHidden( True )

            self.tabledetails.addAction( self.actionDeleteRow )

#            self.tabledetails.horizontalHeader().setStretchLastSection(True)

        self.tabledetails.setColumnHidden( IDARTICULO, True )
        self.tabledetails.setColumnHidden( IDDOCUMENTOT, True )


    def updateDetailFilter( self, index ):
        record = self.navmodel.record( index )
        self.lbltasaiva.setText( record.value( "tasaiva" ).toString() + '%' )
        self.lblanulado.setHidden( record.value( "idestado" ).toInt()[0] != constantes.ANULADO )
        self.anulable = record.value( ANULABLE ).toInt()[0]
#        self.actionAnular.setEnabled()
        escontado = record.value( "escontado" ).toBool()
        if escontado:
            self.rbcontado.setChecked( True )

        else:
            self.rbcredito.setChecked( True )
#            self.recibo.setHidden(True)

        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        self.detailsproxymodel.setFilterRegExp( record.value( "iddocumento" ).toString() )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )

    def updateLabels( self ):
        self.lblsubtotal.setText( moneyfmt( self.editmodel.subtotal, 4, "US$ " ) )
        self.lbliva.setText( moneyfmt( self.editmodel.IVA, 4, "US$ " ) )
        self.lbltotal.setText( moneyfmt( self.editmodel.total, 4, "US$ " ) )
        self.lbltasaiva.setText( str( self.editmodel.ivaTasa ) + '%' )
        self.tabledetails.resizeColumnsToContents()

    def updateModels( self ):
        """
        Recargar todos los modelos
        """
        resultado = False
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo establecer la "\
                                       + "conexión con la base de datos" )


    #        El modelo principal

            query = """
            SELECT
            
                    d.iddocumento,
                    d.ndocimpreso as 'No. Factura',
                    GROUP_CONCAT(IF(pxd.idaccion=%d,p.nombre,"") SEPARATOR '') as Cliente,
                    GROUP_CONCAT(IF(pxd.idaccion=%d,p.nombre,"") SEPARATOR '') as Vendedor,
                    CONCAT('US$ ',FORMAT(ROUND(d.total / (1+ IF(valorcosto IS NULL,0,valorcosto/100)),4),4))  as subtotal,
                    CONCAT('US$ ',FORMAT(d.total- ROUND(d.total / (1+ IF(valorcosto IS NULL,0,valorcosto/100)),4),4))  as iva,
                    CONCAT('US$ ',FORMAT(d.Total,4)) as Total,
                    d.observacion,
                    d.fechacreacion as Fecha,
                    b.nombrebodega as Bodega,
                    tc.tasa as 'Tipo de Cambio Oficial',
                    valorcosto as tasaiva,
                    ed.descripcion as Estado,
                    d.idestado,
                    d.escontado,
                    d.total as totalfac,
                    fnFacturaAnulable(d.iddocumento,d.idtipodoc,%d,%d,%d,%d) as anulable,
                    b.idbodega
                FROM documentos d
                JOIN estadosdocumento ed ON ed.idestado = d.idestado
                JOIN bodegas b ON b.idbodega=d.idbodega
                JOIN tiposcambio tc ON tc.idtc=d.idtipocambio
                JOIN personasxdocumento pxd ON pxd.iddocumento=d.iddocumento
                JOIN personas p ON p.idpersona=pxd.idpersona
                LEFT JOIN costosxdocumento cd ON cd.iddocumento=d.iddocumento
                LEFT JOIN costosagregados ca ON ca.idcostoagregado=cd.idcostoagregado
                WHERE d.idtipodoc=%d
                GROUP BY d.iddocumento
                ORDER BY CAST(IF(ndocimpreso='S/N',0,d.ndocimpreso) AS SIGNED)
                ;
            """ % ( constantes.CLIENTE,
                    constantes.VENDEDOR,
                    constantes.IDRECIBO,
                    constantes.IDNC,
                    constantes.CONFIRMADO,
                    constantes.PENDIENTE,
                    constantes.IDFACTURA )
            self.navmodel.setQuery( query )



    #        Este es el modelo con los datos de la tabla para navegar
            self.detailsmodel.setQuery( u"""
                SELECT
                    ad.idarticulo,
                    ad.descripcion as 'Descripción',
                    -a.unidades as Unidades,
                    CONCAT('US$ ',FORMAT(a.precioventa,4)) as 'Precio Unit.',
                    CONCAT('US$ ',FORMAT(-a.unidades*a.precioventa,4)) as 'Total',
                    a.iddocumento
                FROM articulosxdocumento a
                JOIN vw_articulosdescritos ad on a.idarticulo=ad.idarticulo
                WHERE a.precioventa IS NOT NULL
                ;
            """ )

    #        Este objeto mapea una fila del modelo self.navproxymodel a los controles

            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )

            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.lblnfac, NDOCIMPRESO , "text" )
            self.mapper.addMapping( self.txtobservaciones, OBSERVACION )
            self.mapper.addMapping( self.txtcliente, CLIENTE, "text" )
            self.mapper.addMapping( self.txtvendedor, VENDEDOR, "text" )
            self.mapper.addMapping( self.txtbodega, BODEGA, "text" )
            self.mapper.addMapping( self.lbltotal, TOTAL, "text" )
            self.mapper.addMapping( self.lblsubtotal, SUBTOTAL, "text" )
            self.mapper.addMapping( self.lbliva, IVA, "text" )
            self.mapper.addMapping( self.dtPicker, FECHA )

    #        asignar los modelos a sus tablas

            self.tablenavigation.setModel( self.navproxymodel )
            self.tabledetails.setModel( self.detailsproxymodel )






            resultado = True
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                  unicode( inst ) )
            self.status = True
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(),
                                  u"Hubo un error al actualizar los datos" )
            self.status = True
        finally:
            if self.database.isOpen():
                self.database.close()


        return resultado


    @property
    def valid( self ):
        """
        Un documento es valido cuando 
        self.printedDocumentNumber != ""
        self.providerId !=0
        self.validLines >0
        self.ivaId !=0
        self.uid != 0
        self.warehouseId != 0
        """
        if int( self.editmodel.datosSesion.usuarioId ) == 0:
            raise Exception( "No existe el usuario" )
        elif int( self.editmodel.clienteId ) == 0:
            QMessageBox.warning( self, qApp.organizationName(),
                                  "Por favor elija el cliente" )
            self.cbcliente.setFocus()
        elif int( self.editmodel.vendedorId ) == 0:
            QMessageBox.warning( self, qApp.organizationName(),
                                 "Por favor elija el vendedor" )
            self.cbvendedor.setFocus()
        elif int( self.editmodel.bodegaId ) == 0:
            QMessageBox.warning( self, qApp.organizationName(),
                                  "Por favor elija la bodega" )
            self.cbbodega.setFocus()
        elif int( self.editmodel.validLines ) == 0:
            QMessageBox.warning( self, qApp.organizationName(),
                              "Por favor complete la información de los artículos comprados" )
        else:
            return True
        return False
Ejemplo n.º 22
0
class Helferlein(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        # Oberfläche abbilden:      
        self.ui = uic.loadUi("ui_helferlein.ui")
        self.ui.setWindowIcon(QtGui.QIcon('helferlein.png'))
        #self.db = QSqlDatabase.addDatabase("QMYSQL")
        self.db = QSqlDatabase.addDatabase("QSQLITE3")
        self.db.setHostName("localhost")
        self.db.setDatabaseName("helferlein")
        self.user = "******"
        self.password = "******"
        if self.db.open(self.user, self.password):
            print "DB Verbindung"
            #self.init_db()
        else:
            print "Verbindung konnte nicht hergestellt werden"
        self.sql_model_namensliste = QSqlQueryModel(self)
        self.sql_model_fehlzeiten = QSqlQueryModel(self)
        self.ui.tableView_schuelernamen.setModel(self.sql_model_namensliste)
        self.ui.tableView_fehlzeiten.setModel(self.sql_model_fehlzeiten)


        # Argumente übergeben
        if len(sys.argv) > 1:
            self.filename = sys.argv[1]
            f = open(self.filename,'rb')
   	    self.schuelerliste = pickle.load(f)
            f.close()
            for schueler in self.schuelerliste.values():
                self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname)
                self.ui.listWidget.sortItems(0)
        else:
            self.filename = ''
            self.schuelerliste = {}

        # Grundeinstellungen:
        self.ui.dateEdit.setDate(QtCore.QDate.currentDate())
        self.ui.dateEdit_2.setDate(QtCore.QDate.currentDate())
        self.ui.dateEdit_3.setDate(QtCore.QDate.currentDate())
        self.ui.dateEdit_4.setDate(QtCore.QDate.currentDate())
        self.ui.comboBox_stufenwahl.currentIndexChanged.connect(self.stufenwahl)
        self.ui.show()

        # Connects:
        # Menü
        self.ui.actionStufe_importieren.triggered.connect(self.stufe_importieren)
        self.ui.action_ffnen.triggered.connect(self.datei_oeffnen)
        self.ui.actionSpeichern.triggered.connect(self.datei_speichern)
        self.ui.actionSpeichern_unter.triggered.connect(self.datei_speichern_unter)
        self.ui.actionSch_ler_l_schen.triggered.connect(self.schueler_loeschen)
        self.ui.actionSch_ler_hinzuf_gen.triggered.connect(self.schueler_anlegen)    
        self.ui.actionKrankmeldungen.triggered.connect(self.zeige_krankmeldungen)
        self.ui.actionBeurlaubungen.triggered.connect(self.zeige_beurlaubungen)
        self.ui.actionKlausur_Attest.triggered.connect(self.zeige_klausur_attest)
        self.ui.actionDefizite_suchen.triggered.connect(self.suche_defizite)
        self.ui.actionKlausurplan_konvertieren.triggered.connect(self.klausurplan_konvertieren)

        self.ui.tableView_schuelernamen.activated.connect(self.schueler_auswahl)
        self.ui.tableView_schuelernamen.clicked.connect(self.schueler_auswahl)
        self.ui.lineEdit.textChanged.connect(self.suche)
        self.ui.pushButton_7.clicked.connect(self.heutiges_datum_setzen)
        
        # Krankmeldungen
        self.ui.pushButton.clicked.connect(self.krankmeldung_speichern)
        self.ui.lineEdit_2.returnPressed.connect(self.krankmeldung_speichern)
        self.ui.pushButton_4.clicked.connect(self.eintrag_loeschen_krank)
        self.ui.tableView_fehlzeiten.clicked.connect(self.krankmeldung_aufrufen)

        # Beurlaubungen
        self.ui.pushButton_2.clicked.connect(self.beurlaubung_speichern)
        self.ui.lineEdit_3.returnPressed.connect(self.beurlaubung_speichern)
        self.ui.pushButton_5.clicked.connect(self.eintrag_loeschen_beurlaubung)
        self.ui.tableWidget_2.cellClicked.connect(self.beurlaubung_aufrufen)

        # Bemerkungen
        self.ui.pushButton_3.clicked.connect(self.bemerkung_speichern)
        #self.ui.lineEdit_4.returnPressed.connect(self.bemerkung_speichern)
        self.ui.pushButton_6.clicked.connect(self.eintrag_loeschen_bemerkung)
        self.ui.tableWidget_3.cellClicked.connect(self.bemerkung_aufrufen)

        self.ui.calendarWidget.selectionChanged.connect(self.datum_geaendert)

        #self.ui.tableWidget.cellChanged.connect(self.zeile_geaendert_krank)

    # DB-Methoden ###############################################################

    def init_db(self):
        print "here"
        sql_query = QSqlQuery('''SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA 
                                 WHERE SCHEMA_NAME = 'helferlein';''', self.db)
        size = sql_query.size()
        print size
        if size == 0:
            print "db anlegen"
            sql_query = QSqlQuery("CREATE DATABASE helferlein;", self.db)
            print "tabelle schueler anlegen"
            sql_query = QSqlQuery('''CREATE TABLE SCHUELER (
               id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
               Name CHAR(100),
               Vorname CHAR(100),
               Stufe CHAR(2));''', self.db)
            print "tabelle fehlzeit anlegen"
            sql_query.prepare('''CREATE TABLE FEHLZEIT (
               id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
               schueler_id INT,
               Grund CHAR(100),
               Beginn CHAR(10),
               Ende CHAR(10),
               Stunden INT,
               ist_Beurlaubung INT,
               Attest INT,
               klausur_verpasst INT,
               Schuljahr CHAR(10));''')
            sql_query.exec_()            
       
    def create_db(self):
        self.db.setDatabaseName(FILENAME_DB)
        ok = self.db.open()
        if ok:
            sql_query = QSqlQuery()
            

    # Menü-Methoden:
    def stufe_importieren(self):
        filename = QtGui.QFileDialog.getOpenFileName(self, u'CVS-Datei öffnen','.')
        namens_liste = [[col.strip() for col in row.split(";")] 
                   for row in codecs.open(filename, encoding="iso-8859-15")]
        sql_query = QSqlQuery()
        sql_query.prepare('''INSERT INTO SCHUELER(NAME, VORNAME, STUFE)
                                 VALUES(:name,:vorname,:stufe)''')
        for name, vorname, stufe in namens_liste:          
            sql_query.bindValue(':name',name)
            sql_query.bindValue(':vorname', vorname)
            sql_query.bindValue(':stufe', stufe)
            sql_query.exec_()

    def datei_oeffnen(self):
        self.filename = QtGui.QFileDialog.getOpenFileName(self, u'Datei öffnen','.')
        f = open(self.filename,'rb')
   	self.schuelerliste = pickle.load(f)
        f.close()

        self.ui.listWidget.clear()
        for schueler in self.schuelerliste.values():
            self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname)
        self.ui.listWidget.sortItems(0)

    def datei_speichern(self):
        f = open(self.filename,'wb')
   	pickle.dump(self.schuelerliste,f)
        f.close()

    def datei_speichern_unter(self):
        filename = QtGui.QFileDialog.getSaveFileName(self, u'Namen der Datei angeben','.')
        f = open(filename,'wb')
   	pickle.dump(self.schuelerliste,f)
        f.close()

    def schueler_loeschen(self):
        if self.ui.label_3.text():
            name, vorname = self.ui.label_3.text().split(', ')
            reply = QtGui.QMessageBox.question(self, "Achtung!",
                         "Soll %s, %s wirklich gelöscht werden?" % (name,vorname),
                         QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                del self.schuelerliste[(vorname,name)]
                self.ui.listWidget.clear()
                for schueler in self.schuelerliste.values():
                    self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname)
                    self.ui.listWidget.sortItems(0)
                self.datei_speichern()
                self.ui.label_3.setText("")
                self.ui.label_10.setText("")
                self.ui.label_16.setText("")

        else: 
             MESSAGE = u"<p>Bitte erst einen Schüler aus der Liste auswählen</p>"
             reply = QtGui.QMessageBox.information(self,
                "Achtung!", MESSAGE)
            
    def schueler_anlegen(self):
        dialog_anlegen = Dialog_Schueler_Anlegen(self)
        dialog_anlegen.ui.setWindowTitle(u'Schüler/in hinzufügen')
        if dialog_anlegen.ui.exec_() == 1:
            name = dialog_anlegen.ui.lineEdit_name.text()
            vorname = dialog_anlegen.ui.lineEdit_vorname.text()              
            stufe = dialog_anlegen.ui.spinBox_stufe.value() 
            schueler = Schueler(vorname, name, stufe)
            if schueler not in self.schuelerliste:
                self.schuelerliste[(vorname, name)] = schueler
                self.ui.listWidget.clear()
                for schueler in self.schuelerliste.values():
                    self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname)
                    self.ui.listWidget.sortItems(0)
                self.datei_speichern()
                self.ui.label_3.setText("")
                self.ui.label_10.setText("")
                self.ui.label_16.setText("")
            
  
    # Fenster-Methoden:
    def stufenwahl(self, index):
        print "stufenwahl", index
        query = '''SELECT id, Name, Vorname FROM SCHUELER 
                   WHERE Stufe='{}' ORDER BY Name;'''.\
                   format(self.ui.comboBox_stufenwahl.itemText(index))
        print query
        sql_query = QSqlQuery(query)
        self.sql_model_namensliste.setQuery(sql_query)
        sql_query.exec_()
        self.ui.tableView_schuelernamen.hideColumn(0) #don't show id

    def schueler_auswahl(self, index):
        self.schueler_id = index.sibling(index.row(),0).data().toString()
        name = index.sibling(index.row(),1).data().toString()
        vorname = index.sibling(index.row(),2).data().toString()
        self.ui.label_3.setText(u'{}, {}'.format(name, vorname))
        self.ui.label_10.setText(u'{}, {}'.format(name, vorname))
        self.ui.label_16.setText(u'{}, {}'.format(name, vorname))
        self.tabelle_krank_aktualisieren()

    def heutiges_datum_setzen(self):
        self.ui.calendarWidget.setSelectedDate(QtCore.QDate.currentDate())    

    def tabelle_krank_aktualisieren(self):
        query_string = '''SELECT id, Beginn, Ende, Attest, klausur_verpasst
                          as Klausur, Grund FROM FEHLZEIT 
                          WHERE FEHLZEIT.schueler_id={} AND ist_beurlaubung = '0';
                       '''.format(self.schueler_id)
        print query_string
        sql_query = QSqlQuery(query_string)
        self.sql_model_fehlzeiten.setQuery(sql_query)
        self.ui.tableView_fehlzeiten.hideColumn(0) #don't show id
        sql_query.exec_()
        self.ui.tableView_fehlzeiten.resizeColumnsToContents()
        self.ui.tableView_fehlzeiten.horizontalHeader().setStretchLastSection(True)

    def tabelle_beurlaubung_aktualisieren(self,schueler):
        self.ui.tableWidget_2.setRowCount(len(schueler.beurlaubungen.keys()))
        zeile = 0
        for eintrag in sorted(schueler.beurlaubungen.keys(),reverse=True):
            liste = schueler.beurlaubungen[eintrag]
            liste0 = [eintrag.toString("dd.MM.yyyy"), 
                      liste[0].toString("dd.MM.yyyy"),
                      str(liste[1]), 
                      liste[2]]
            for spalte in range(4):
               item = QtGui.QTableWidgetItem(liste0[spalte])
               self.ui.tableWidget_2.setItem(zeile, spalte, item);
            zeile += 1
        self.ui.tableWidget_2.resizeColumnsToContents()
        self.ui.tableWidget_2.horizontalHeader().setStretchLastSection(True)

    def tabelle_bemerkung_aktualisieren(self,schueler):
        self.ui.tableWidget_3.setRowCount(len(schueler.bemerkungen.keys()))
        zeile = 0
        for eintrag in sorted(schueler.bemerkungen.keys(),reverse=True):
            aktennotiz = ('ja' if schueler.bemerkungen[eintrag][1] else 'nein')
            bemerkung = schueler.bemerkungen[eintrag][0] 
            liste0 = [eintrag.toString("dd.MM.yyyy"),aktennotiz, bemerkung]
            for spalte in range(3):
               item = QtGui.QTableWidgetItem(liste0[spalte])
               self.ui.tableWidget_3.setItem(zeile, spalte, item);
            zeile += 1
        self.ui.tableWidget_3.resizeColumnsToContents()
        self.ui.tableWidget_3.horizontalHeader().setStretchLastSection(True)
        self.ui.plainTextEdit.clear()
        
    def ui_zuruecksetzen(self):
        self.ui.lineEdit.clear()
        self.ui.lineEdit_2.clear()
        self.ui.lineEdit_3.clear()
        #self.ui.lineEdit_4.clear()
        self.ui.plainTextEdit.clear()
        self.ui.checkBox.setChecked(False)
        self.ui.checkBox_2.setChecked(False)
        self.ui.checkBox_3.setChecked(False)
        self.ui.spinBox.setValue(0)
        self.ui.calendarWidget.setSelectedDate(QtCore.QDate.currentDate())
    
    def suche(self,text):
        self.ui.listWidget.clear()
        for schueler in self.schuelerliste:
            if schueler[0].contains(text,0) or schueler[1].contains(text,0):
                s = self.schuelerliste[schueler]
                self.ui.listWidget.addItem(s.name + ', ' + s.vorname)
        self.ui.listWidget.sortItems(0)

    def datum_geaendert(self):
        datum_aktuell = self.ui.calendarWidget.selectedDate()
        self.ui.dateEdit.setDate(datum_aktuell)
        self.ui.dateEdit_2.setDate(datum_aktuell)
        self.ui.dateEdit_3.setDate(datum_aktuell)
        self.ui.dateEdit_4.setDate(datum_aktuell)

    def krankmeldung_speichern(self):
        self.schuljahr = '2013/14'
        datum_von = self.ui.dateEdit.date().toString("dd.MM.yyyy")
        datum_bis = self.ui.dateEdit_2.date().toString("dd.MM.yyyy")
        grund = (unicode(self.ui.lineEdit_2.text()) if self.ui.lineEdit_2.text() else u'-')
        attest = (u'ja' if self.ui.checkBox.isChecked() else u'nein')
        klausur = (u'ja' if self.ui.checkBox_2.isChecked() else u'nein')
        sql_query = QSqlQuery()
        query_string = '''INSERT INTO FEHLZEIT (schueler_id, Grund, Beginn, 
                             Ende, Attest, klausur_verpasst, ist_beurlaubung, schuljahr)
                             VALUES({},'{}','{}','{}','{}','{}','0','{}');'''.format(self.schueler_id,
                             grund, datum_von, datum_bis, attest, klausur, self.schuljahr)
        #print query_string
        sql_query.prepare(query_string)
        sql_query.exec_()
        self.ui_zuruecksetzen()
        self.tabelle_krank_aktualisieren()

    def eintrag_loeschen_krank(self):
        selected_items = self.ui.tableView_fehlzeiten.selectionModel().selection().indexes()
        if selected_items:
            index = selected_items[0]
            zeile = index.row()
            fehlzeit_id = index.sibling(zeile,0).data().toString()
            reply = QtGui.QMessageBox.question(self, "Achtung!",
                         u"Soll die markierte Zeile wirklich gelöscht werden?",
                         QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
            if reply == QtGui.QMessageBox.Yes:
                print "Zeile löschen", fehlzeit_id
                sql_query = QSqlQuery('''DELETE FROM FEHLZEIT
                                         WHERE id = {}'''.format(fehlzeit_id))
                sql_query.exec_()
                self.tabelle_krank_aktualisieren()
        else:
            QtGui.QMessageBox.information(self, "Achtung!", "Bitte erst eine Zeile markieren!")

    def krankmeldung_aufrufen(self,index):
        zeile = index.row()
        sql_record = self.sql_model_fehlzeiten.record(zeile) 
        beginn = sql_record.value('Beginn').toString()
        ende = sql_record.value('Ende').toString()
        attest = sql_record.value('Attest').toString() == 'ja'
        klausur = sql_record.value('Klausur').toString() == 'ja'
        grund = sql_record.value('Grund').toString()
        self.ui.dateEdit.setDate(QtCore.QDate.fromString(beginn,"dd.MM.yyyy"))
        self.ui.dateEdit_2.setDate(QtCore.QDate.fromString(ende,"dd.MM.yyyy"))
        self.ui.checkBox.setChecked(attest)
        self.ui.checkBox_2.setChecked(klausur)
        self.ui.lineEdit_2.setText(grund)

    def beurlaubung_speichern(self):
        name, vorname = self.ui.label_10.text().split(', ')
        schueler = self.schuelerliste[(vorname,name)]
        datum_von = self.ui.dateEdit_3.date()
        datum_bis = self.ui.dateEdit_4.date()
        grund = (self.ui.lineEdit_3.text() if self.ui.lineEdit_3.text() else u'-')
        anzahl_stunden = self.ui.spinBox.value()
        schueler.beurlaubungen[datum_von]=[datum_bis,anzahl_stunden,grund]
        self.ui_zuruecksetzen()
        self.tabelle_beurlaubung_aktualisieren()
        self.datei_speichern()

    def beurlaubung_aufrufen(self,zeile,spalte):
        self.ui.dateEdit_3.setDate(QtCore.QDate.fromString(self.ui.tableWidget_2.item(zeile,0).text(),"dd.MM.yyyy"))
        self.ui.dateEdit_4.setDate(QtCore.QDate.fromString(self.ui.tableWidget_2.item(zeile,1).text(),"dd.MM.yyyy"))
        self.ui.spinBox.setValue(int(self.ui.tableWidget_2.item(zeile,2).text()))
        self.ui.lineEdit_3.setText(self.ui.tableWidget_2.item(zeile,3).text())

    def bemerkung_speichern(self):
        name, vorname = self.ui.label_16.text().split(', ')
        schueler = self.schuelerliste[(vorname,name)]
        datum = self.ui.calendarWidget.selectedDate()
        bemerkung = self.ui.plainTextEdit.document().toPlainText()
        if not bemerkung:
           QtGui.QMessageBox.information(self,u"Achtung!", u"Bitte erst eine Bemerkung eingeben!")
        else:
            schueler.bemerkungen[datum]=[bemerkung,self.ui.checkBox_3.isChecked()]
            self.tabelle_bemerkung_aktualisieren(schueler)
            self.datei_speichern()
            if self.ui.checkBox_3.isChecked():
                printer = QtGui.QPrinter()
                printer.setPaperSize(QtGui.QPrinter.A4)
                kopfzeile = u'Aktennotiz von ' + vorname + ' ' + name + u' am ' + datum.toString("dd.MM.yyyy") + ':\n\n'
                #kopfzeile = u'<b>Aktennotiz von ' + vorname + ' ' + name + u' am ' + datum.toString("dd.MM.yyyy") + ':</b><br /><br />'
                doc = QtGui.QTextDocument(kopfzeile + bemerkung)
                #doc.setHtml(kopfzeile + bemerkung)
                doc.print_(printer)
            self.ui_zuruecksetzen()

    def bemerkung_aufrufen(self,zeile,spalte):
        #print zeile, spalte
        self.ui.calendarWidget.setSelectedDate(QtCore.QDate.fromString(self.ui.tableWidget_3.item(zeile,0).text(),"dd.MM.yyyy"))
        self.ui.plainTextEdit.setPlainText(self.ui.tableWidget_3.item(zeile,2).text())
        if self.ui.tableWidget_3.item(zeile,1).text()=='ja':
            self.ui.checkBox_3.setChecked(True)
        else:
            self.ui.checkBox_3.setChecked(False)
            

    def eintrag_loeschen_beurlaubung(self):
        name, vorname = self.ui.label_10.text().split(', ')
        schueler = self.schuelerliste[(vorname,name)]
        i, ok = QtGui.QInputDialog.getInteger(self,
                u"Zeile löschen", u"Welche Zeile soll gelöscht werden?",1,1 ,len(schueler.beurlaubungen.keys()), 1)
        if ok:
            datum = QtCore.QDate.fromString(self.ui.tableWidget_2.item(i-1,0).text(),"dd.MM.yyyy")
            del schueler.beurlaubungen[datum]
            self.tabelle_beurlaubung_aktualisieren(schueler)
            self.datei_speichern()

    def eintrag_loeschen_bemerkung(self):
        name, vorname = self.ui.label_16.text().split(', ')
        schueler = self.schuelerliste[(vorname,name)]
        i, ok = QtGui.QInputDialog.getInteger(self,
                u"Zeile löschen", u"Welche Zeile soll gelöscht werden?",1,1 ,len(schueler.bemerkungen.keys()), 1)
        if ok:
            datum = QtCore.QDate.fromString(self.ui.tableWidget_3.item(i-1,0).text(),"dd.MM.yyyy")
            del schueler.bemerkungen[datum]
            self.tabelle_bemerkung_aktualisieren(schueler)
            self.datei_speichern()

    def zeile_geaendert_krank(self,zeile,spalte):
        print self.ui.tableWidget.item(zeile,spalte).text()
        if self.ui.tableWidget.item(zeile,spalte).text() != '':
            name, vorname = self.ui.label_3.text().split(', ')
            schueler = self.schuelerliste[(vorname,name)]
            datum = QtCore.QDate.fromString(self.ui.tableWidget.item(zeile,0).text(),"dd.MM.yyyy")
            datum_bis = QtCore.QDate.fromString(self.ui.tableWidget.item(zeile,1).text(),"dd.MM.yyyy")
            attest = self.ui.tableWidget.item(zeile,2).text()
            grund = self.ui.tableWidget.item(zeile,3).text()
            schueler.krankmeldungen[datum]=[datum_bis,attest,grund]
            self.datei_speichern()

    #Statistiken
    def zeige_krankmeldungen(self):
        dialog_krank = Dialog_Tabelle(self)
        dialog_krank.ui.setWindowTitle(u'Krankmeldungen')
        dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste))
        dialog_krank.ui.tableWidget.setColumnCount(2)
        dialog_krank.ui.tableWidget.setHorizontalHeaderLabels([u'Name, Vorname',u'Tage krank'])
  
        schueler_krank = []
        for schueler in self.schuelerliste.values():
            tage = 0
            for datum in schueler.krankmeldungen.keys():
                tage += datum.daysTo(schueler.krankmeldungen[datum][0])+1
            schueler_krank.append([schueler.name+ ', ' + schueler.vorname,str(tage)])

        zeile = 0
        for eintrag in sorted(schueler_krank, key= lambda schueler : int(schueler[1]), reverse=True):
            for spalte in range(2):
               item = QtGui.QTableWidgetItem(eintrag[spalte])
               if spalte == 1:
                   item.setTextAlignment(4)
               dialog_krank.ui.tableWidget.setItem(zeile, spalte, item);
            zeile += 1
        dialog_krank.ui.tableWidget.resizeColumnsToContents()
        dialog_krank.ui.tableWidget.resizeRowsToContents() 
        dialog_krank.ui.tableWidget.horizontalHeader().setStretchLastSection(True)
        

    def zeige_beurlaubungen(self):
        dialog_krank = Dialog_Tabelle(self)
        dialog_krank.ui.setWindowTitle(u'Beurlaubungen')
        dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste))
        dialog_krank.ui.tableWidget.setColumnCount(2)
        dialog_krank.ui.tableWidget.setHorizontalHeaderLabels([u'Name, Vorname',u'Stunden beurlaubt'])

        schueler_beurlaubt = []
        for schueler in self.schuelerliste.values():
            stunden = 0
            for datum in schueler.beurlaubungen:
                stunden += schueler.beurlaubungen[datum][1]
            schueler_beurlaubt.append([schueler.name+ ', ' + schueler.vorname,str(stunden)])

        zeile = 0
        for eintrag in sorted(schueler_beurlaubt, key= lambda schueler : int(schueler[1]), reverse=True):
            for spalte in range(2):
               item = QtGui.QTableWidgetItem(eintrag[spalte])
               if spalte == 1:
                   item.setTextAlignment(4)
               dialog_krank.ui.tableWidget.setItem(zeile, spalte, item);
            zeile += 1
        dialog_krank.ui.tableWidget.resizeColumnsToContents()


    def zeige_klausur_attest(self):
        dialog_krank = Dialog_Tabelle(self)
        dialog_krank.ui.setWindowTitle(u'versäumte Klausuren')
        dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste))
        dialog_krank.ui.tableWidget.setColumnCount(3)    

    def suche_defizite(self):
        MESSAGE = u"<p>Die Eingabedatei muss im CSV-Format (als Trennzeichen Komma) vorliegen.</p>" \
            u"<p>Die Ausgabedatei wird in demselben Verzeichnis erzeugt, wo die Eingabedatei liegt.\
                 Sie hat den gleichen Namen mit dem Zusatz '_defizite'.\<p>Sollte etwas nicht funktionieren, frag Boris ;).</p>"
        reply = QtGui.QMessageBox.information(self,
                "Achtung!", MESSAGE)
        if reply == QtGui.QMessageBox.Ok:
            items = ("Noten", "Punkte")
            item, ok = QtGui.QInputDialog.getItem(self, "Abfrage",
                                                   "Wie sind die Noten eingeben?\nAls...", items, 0, False)
            if ok and item:
                print item
                csv_ein = QtGui.QFileDialog.getOpenFileName(self, u'CSV-Datei öffnen','.')
                if csv_ein:
                    finde_defizite(str(csv_ein), str(item))

    def klausurplan_konvertieren(self):
        MESSAGE = u"<p>Die Eingabedatei muss im CSV-Format vorliegen\
                  Es dürfen keine Kommata in den Bemerkungen vorkommen!</p>"\
             u"<p>Die Ausgabedatei wird in demselben Verzeichnis erzeugt, wo die Eingabedatei liegt.\
                  Sie hat den gleichen Namen mit dem Zusatz '_konvertiert'.\
                  Es öffnet sich nun ein Fenster, wo man die Eingabedatei auswählen kann.</p>"\
            u"<p>Sollte etwas nicht funktionieren, frag Boris ;).</p>"
        reply = QtGui.QMessageBox.information(self,
                "Achtung!", MESSAGE)
        if reply == QtGui.QMessageBox.Ok:
            csv_ein = QtGui.QFileDialog.getOpenFileName(self, u'CSV-Datei öffnen','.')
            if csv_ein:
                konvertiere(str(csv_ein))
Ejemplo n.º 23
0
class FrmArqueo( Ui_frmArqueo, Base ):
    '''
    Esta clase implementa el formulario arqueo
    '''
    web = "arqueos.php?doc="
    def __init__( self, datos_sesion, parent, edit = False ):
        u'''
        @param datos_sesion: La información de la sesion de caja
        '''
        super( FrmArqueo, self ).__init__( parent, True )
        self.sesion = datos_sesion
        self.setWindowModality( Qt.WindowModal )
        self.setWindowFlags( Qt.Dialog )
#        self.status = False 

        self.__dolar_proxy = ArqueoProxyModel()
        self.__cordoba_proxy = ArqueoProxyModel()
                    
        
        self.editmodel = None

#        El modelo principal
        self.navmodel = QSqlQueryModel( self )
    #        El modelo que filtra a self.navmodel
        self.navproxymodel = QSortFilterProxyModel( self )
        self.__details_proxymodel_d = QSortFilterProxyModel( self )
        self.__details_proxymodel_c = QSortFilterProxyModel( self )
        
        
        self.navproxymodel.setSourceModel( self.navmodel )
#        Este es el modelo con los datos de la tabla con los detalles
        self.detailsModel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )
        self.detailsproxymodel.setSourceModel( self.detailsModel )

        #filtrar en dolares y en cordobas
        
        self.__details_proxymodel_d.setSourceModel( self.detailsproxymodel )
        self.__details_proxymodel_d.setFilterKeyColumn( MONEDA )
        self.__details_proxymodel_d.setFilterRegExp( "^%d$" % constantes.IDDOLARES )

    
        self.__details_proxymodel_c.setSourceModel( self.detailsproxymodel )
        self.__details_proxymodel_c.setFilterKeyColumn( MONEDA )
        self.__details_proxymodel_c.setFilterRegExp( "^%d$" % constantes.IDCORDOBAS )
           
        
        
        if edit:
            self.status = False
            self.newDocument()
            self.actionCancel.setVisible(False)
            self.tabWidget.setTabEnabled(1,False)
        else:
            self.status = True
            QTimer.singleShot( 0, self.loadModels )

    def updateModels( self ):
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( "No se pudo abrir la base de datos" )

            #TODO: Esta consulta tiene que mejorar para definir realmente quien es el que realiza el arqueo
            query = u"""
            SELECT
                d.iddocumento,
                d.fechacreacion ,
                p.nombre AS 'Arqueador',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOEFECTIVO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'efectivoc',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOEFECTIVO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'efectivod',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOCHEQUE ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'chequec',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOCHEQUE ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'chequed',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGODEPOSITO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'depositoc',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGODEPOSITO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'depositod',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTRANSFERENCIA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'transferenciac',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTRANSFERENCIA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'transferenciad',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTARJETA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'tarjetac',
                FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTARJETA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'tarjetad'
            FROM documentos d
            JOIN movimientoscaja mc ON mc.iddocumento = d.iddocumento
            JOIN tiposmoneda tm ON mc.idtipomoneda = tm.idtipomoneda
            JOIN personasxdocumento pxd ON pxd.iddocumento = d.iddocumento
            JOIN personas p ON p.idpersona = pxd.idpersona
            WHERE d.idtipodoc =  %d
            GROUP BY d.iddocumento
            """ % ( constantes.IDARQUEO )
            self.navmodel.setQuery( query )

            self.detailsModel.setQuery( u"""
            SELECT
                l.cantidad AS 'Cantidad',
                CONCAT_WS(' ',tm.simbolo, CAST(de.valor AS CHAR)) as 'Denominación',
                FORMAT(l.cantidad * de.valor, 4) as 'Total',
                de.idtipomoneda,
                l.iddocumento
            FROM lineasarqueo l
            JOIN denominaciones de ON de.iddenominacion = l.iddenominacion
            JOIN tiposmoneda tm ON de.idtipomoneda = tm.idtipomoneda
            JOIN documentos d ON d.iddocumento = l.iddocumento
            JOIN tiposcambio tc ON d.idtipocambio = tc.idtc
            """ )

            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )
            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.lblUserName, NOMBRE, "value" )
            self.mapper.addMapping( self.sbCkC, CHEQUEC, "value" )
            self.mapper.addMapping( self.sbCkD, CHEQUED, "value" )
            self.mapper.addMapping( self.sbCardC, TARJETAC, "value" )
            self.mapper.addMapping( self.sbCardD, TARJETAD, "value" )
            self.mapper.addMapping( self.sbDepositC, DEPOSITOC, "value" )
            self.mapper.addMapping( self.sbDepositD, DEPOSITOD, "value" )
            self.mapper.addMapping( self.sbTransferC  , TRANSFERENCIAC, "value" )
            self.mapper.addMapping( self.sbTransferD  , TRANSFERENCIAD, "value" )



        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
        finally:
            if self.database.isOpen():
                self.database.close()

    def updateDetailFilter( self, index ):
        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMMENTOT )
        self.detailsproxymodel.setFilterRegExp( self.navmodel.record( index ).value( IDDOCUMMENTO ).toString() )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )

    def setControls( self, status ):
        """
        @param status: false = editando true = navegando 
        """
        self.actionPrint.setVisible( status )
        self.tablenavigation.setEnabled( status )
        self.tabnavigation.setEnabled( status )

        self.actionNew.setVisible( status )
        self.actionPreview.setVisible( status )

        self.actionCancel.setVisible( not status )
        self.actionSave.setVisible( not status )
        self.actionGoFirst.setVisible(  status )
        self.actionGoLast.setVisible(  status )
        self.actionGoNext.setVisible(  status )
        self.actionGoPrevious.setVisible(  status )

        self.sbCkD.setReadOnly( status )
        self.sbCkC.setReadOnly( status )
        self.sbCardD.setReadOnly( status )
        self.sbCardC.setReadOnly( status )
        self.sbDepositD.setReadOnly( status )
        self.sbDepositC.setReadOnly( status )
        self.sbTransferD.setReadOnly( status )
        self.sbTransferC.setReadOnly( status )

        self.txtObservations.setReadOnly( status )

        self.tablenavigation.setColumnHidden( IDDOCUMMENTO, True )


        if not self.status:
            self.tabledetailsC.setEditTriggers( QTableView.AllEditTriggers )
            self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, False )
            self.tabledetailsD.setEditTriggers( QTableView.AllEditTriggers )
            self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, False )
            self.tabWidget.setCurrentIndex( 0 )

            self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, True )
            self.tabledetailsC.setColumnHidden( IDDENOMINACION, True )

            self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, True )
            self.tabledetailsD.setColumnHidden( IDDENOMINACION, True )


#            doublevalidator = QDoubleValidator(0, 99999999, 4, self)

        else:
            self.tabledetailsC.setModel( self.__details_proxymodel_c )
            self.tabledetailsD.setModel( self.__details_proxymodel_d )


            self.tablenavigation.setModel( self.navproxymodel )
            self.tablenavigation.setColumnHidden( IDDOCUMMENTO, True )



            self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, True )
            self.tabledetailsC.setColumnHidden( IDDENOMINACION, True )

            self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, True )
            self.tabledetailsD.setColumnHidden( IDDENOMINACION, True )




        self.tabledetailsC.setColumnHidden( MONEDA, True )
        self.tabledetailsD.setColumnHidden( MONEDA, True )

    def updateLabels( self ):
        self.lblCashC.setText( "%s / %s" % ( 
                        moneyfmt( self.editmodel.totalCashC, 4, "C$" ),
                        moneyfmt( self.editmodel.expectedCashC, 4, "C$" ) )
        )
        self.lblCashD.setText( "%s / %s" % ( 
                        moneyfmt( self.editmodel.totalCashD, 4, "US$" ),
                        moneyfmt( self.editmodel.expectedCashD, 4, "US$" ) )
        )

        self.lblCkC.setText( moneyfmt( self.editmodel.expectedCkC, 4, "C$" ) )
        self.lblCkD.setText( moneyfmt( self.editmodel.expectedCkD, 4, "US$" ) )

        self.lblCardC.setText( 
                        moneyfmt( self.editmodel.expectedCardC, 4, "C$" ) )
        self.lblCardD.setText( 
                        moneyfmt( self.editmodel.expectedCardD, 4, "US$" ) )

        self.lblDepositC.setText( 
                         moneyfmt( self.editmodel.expectedDepositC, 4, "C$" ) )
        self.lblDepositD.setText( 
                         moneyfmt( self.editmodel.expectedDepositD, 4, "US$" ) )

        self.lblTransferC.setText( 
                          moneyfmt( self.editmodel.expectedDepositC, 4, "C$" ) )
        self.lblTransferD.setText( 
                          moneyfmt( self.editmodel.expectedDepositD, 4, "US$" ) )

    def newDocument( self ):
        """
        cargar todos los modelos para la edición
        """
        query = QSqlQuery()
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo establecer la conexión con la base de datos" )
            for window in self.parentWindow.findChild( QMdiArea ).subWindowList():
                if window.widget():
                    raise UserWarning( u"Por favor cierre las otras pestañas"
                                       + u" de la aplicación antes de continuar"
                                       + " con el arqueo" )


            self.editmodel = ArqueoModel( self.sesion )

            self.editmodel.datetime.setDate( self.sesion.fecha )
            self.editmodel.datetime.setTime( QTime.currentTime() )


            self.__dolar_proxy.setSourceModel( self.editmodel )
            self.__dolar_proxy.setFilterKeyColumn( MONEDA )
            self.__dolar_proxy.setFilterRegExp( r"^%d$" % constantes.IDDOLARES )
            self.__dolar_proxy.setDynamicSortFilter( True )


            self.__cordoba_proxy.setSourceModel( self.editmodel )
            self.__cordoba_proxy.setFilterKeyColumn( MONEDA )
            self.__cordoba_proxy.setFilterRegExp( r"^%d$" % constantes.IDCORDOBAS )
            self.__cordoba_proxy.setDynamicSortFilter( True )

            self.tabledetailsC.setModel( self.__cordoba_proxy )
            self.tabledetailsD.setModel( self.__dolar_proxy )

            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( "No se pudo conectar con la base de datos" )

            #verificar si hay documentos pendientes de aprobación
            q = """
            SELECT
                CONCAT_WS(' ', td.descripcion, d.ndocimpreso)
            FROM documentos sesion
            JOIN docpadrehijos dpd ON dpd.idpadre = sesion.iddocumento
            JOIN documentos d ON dpd.idhijo  = d.iddocumento
            JOIN tiposdoc td ON td.idtipodoc = d.idtipodoc
            WHERE d.idestado NOT IN ( %d,%d)
            """ % ( constantes.CONFIRMADO,
                    constantes.ANULADO )
            if not query.exec_( q ):
                raise Exception( u"No se pudo ejecutar la consulta para "\
                                 + "determinar si existen documentos "
                                 + "pendientes de aprobación" )
            if not query.size() == 0:
                raise UserWarning( u"Existen documentos pendientes de "\
                                   + "aprobación en la sesión" )


            #Obtener los datos de la sesión
            q = """
            CALL spConsecutivo( %d, NULL )
            """ % constantes.IDARQUEO
            #query.prepare( q )

            if not query.exec_( q ):
                raise Exception( u"No se pudo ejecutar la consulta para "\
                                 + "obtener el numero del arqueo" )
            if not query.size() > 0:
                raise Exception( u"La consulta para obtener el numero del "\
                                 + "arqueo no devolvio ningún valor" )
            query.first()

            self.editmodel.printedDocumentNumber = query.value( 0 ).toString()
            self.editmodel.exchangeRateId = self.sesion.tipoCambioId
            self.editmodel.exchangeRate = self.sesion.tipoCambioOficial

            self.editmodel.datetime.setDate( self.sesion.fecha )

            q = """
            CALL spTotalesSesion(%d);
            """ % self.sesion.sesionId

            if not query.exec_( q ):
                raise UserWarning( u"No se pudieron calcular los totales"\
                                   + " de la sesión" )
            while query.next():
                if query.value( 0 ).toInt()[0] == constantes.IDPAGOEFECTIVO and query.value( 2 ).toInt()[0] == constantes.IDDOLARES:
                    self.editmodel.expectedCashD = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOEFECTIVO and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS:
                    self.editmodel.expectedCashC = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOCHEQUE and query.value( 2 ).toInt()[0] == constantes.IDDOLARES:
                    self.editmodel.expectedCkD = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOCHEQUE and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS:
                    self.editmodel.expectedCkC = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGODEPOSITO and query.value( 2 ).toInt()[0] == constantes.IDDOLARES:
                    self.editmodel.expectedDepositD = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGODEPOSITO  and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS:
                    self.editmodel.expectedDepositC = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTRANSFERENCIA  and query.value( 2 ).toInt()[0] == constantes.IDDOLARES:
                    self.editmodel.expectedTransferD = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTRANSFERENCIA  and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS:
                    self.editmodel.expectedTransferC = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTARJETA  and query.value( 2 ).toInt()[0] == constantes.IDDOLARES:
                    self.editmodel.expectedCardD = Decimal( query.value( 5 ).toString() )
                elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTARJETA  and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS:
                    self.editmodel.expectedCardC = Decimal( query.value( 5 ).toString() )

            q = """
            SELECT
                d.iddenominacion,
                CONCAT_WS( ' ',d.valor, m.moneda),
                d.valor,
                d.idtipomoneda,
                m.simbolo
            FROM denominaciones d
            JOIN tiposmoneda m ON d.idtipomoneda = m.idtipomoneda
            WHERE d.activo = 1
            ORDER BY d.idtipomoneda, d.valor
            """
            if not query.exec_( q ):
                raise UserWarning( "No se pudo recuperar la lista de "
                                   + "denominaciones" )
            denominationsmodelC = SingleSelectionModel()
            denominationsmodelC.headers = ["Id",
                                            u"Denominación",
                                            "Valor",
                                            "Id Moneda",
                                            "Simbolo"]
            denominationsmodelD = SingleSelectionModel()
            denominationsmodelD.headers = denominationsmodelC.headers


            while query.next():
                if query.value( 3 ).toInt()[0] == constantes.IDDOLARES:
                    denominationsmodelD.items.append( [
                                                  query.value( 0 ).toInt()[0], #el id del tipo de denominacion
                                                  query.value( 1 ).toString(), #La descripción de la denominación
                                                  query.value( 2 ).toString(), # el valor de la denominación
                                                  query.value( 3 ).toInt()[0], #El id del tipo de moneda
                                                  query.value( 4 ).toString() #El simbolo de la moneda
                                                  ] )
                else:
                    denominationsmodelC.items.append( [
                                                  query.value( 0 ).toInt()[0], #el id del tipo de denominacion
                                                  query.value( 1 ).toString(), #La descripción de la denominación
                                                  query.value( 2 ).toString() , # el valor de la denominación
                                                  query.value( 3 ).toInt()[0], #El id del tipo de moneda
                                                  query.value( 4 ).toString() #El simbolo de la moneda
                                                  ] )

            delegateC = ArqueoDelegate( denominationsmodelC )
            self.tabledetailsC.setItemDelegate( delegateC )

            delegateD = ArqueoDelegate( denominationsmodelD )
            self.tabledetailsD.setItemDelegate( delegateD )

            self.addLine()
            self.addLine()
            self.editmodel.setData( self.editmodel.index( 0, MONEDA ), constantes.IDDOLARES )
            self.editmodel.setData( self.editmodel.index( 1, MONEDA ), constantes.IDCORDOBAS )

            self.dtPicker.setDateTime( self.editmodel.datetime )

            self.lblUserName.setText( self.user.fullname )
            self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )

            self.tabledetailsC.setColumnWidth( DENOMINACION, 200 )
            self.tabledetailsD.setColumnWidth( DENOMINACION, 200 )
            self.updateLabels()
            self.status = False

        except UserWarning as inst:
            logging.error( unicode( inst ) )
            logging.error( query.lastError().text() )
            QMessageBox.critical( self,
                                  qApp.organizationName(),
                                  unicode( inst ) )
            self.status = True
        except Exception  as inst:
            logging.critical( unicode( inst ) )
            logging.critical( query.lastError().text() )
            QMessageBox.critical( self,
                                  qApp.organizationName(),
                               "El sistema no pudo iniciar un nuevo arqueo" )
            self.status = True
        finally:
            if self.database.isOpen():
                self.database.close()

    @pyqtSlot( QDateTime )
    def on_dtPicker_dateTimeChanged( self, datetime ):
        pass

    def cancel( self ):
        self.editmodel = None

        self.status = True
        self.navigate( 'last' )

    def save( self ):
        """
        Redefiniendo el metodo save de Base para mostrar 
        advertencias si el arqueo no concuerda
        """
        try:
            errors = []

            if not self.editmodel.totalCashC == self.editmodel.expectedCashC:
                errors.append( u"El total de efectivo en cordobas del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalCashD == self.editmodel.expectedCashD:
                errors.append( u"El total de efectivo en dolares del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalCkD == self.editmodel.expectedCkD:
                errors.append( u"El total de cheques en dolares del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalCkC == self.editmodel.expectedCkC:
                errors.append( u"El total de cheques en cordobas del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalTransferD == self.editmodel.expectedTransferD:
                errors.append( u"El total de transferencias en dolares del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalTransferC == self.editmodel.expectedTransferC:
                errors.append( u"El total de transferencias en cordobas del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalDepositD == self.editmodel.expectedDepositD:
                errors.append( u"El total de depositos en dolares del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalDepositC == self.editmodel.expectedDepositC:
                errors.append( u"El total de depositos en cordobas del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalCardD == self.editmodel.expectedDepositD:
                errors.append( u"El total de pagos en tarjetas en dolares del arqueo no coincide con el de la sesión" )
            if not self.editmodel.totalCardD == self.editmodel.expectedDepositC:
                errors.append( u"El total de pagos en tarjetas en cordobas del arqueo no coincide con el de la sesión" )

            if len( errors ) > 0:
                raise UserWarning( "\n".join( errors ) )
            dlgUser = dlgSmallUserLogin()
            if dlgUser.exec_() == QDialog.Accepted:
                if dlgUser.user.valid and dlgUser.user.hasRole( 'gerencia' ):
                    self.editmodel.authorizationId = dlgUser.user.uid
                    super( FrmArqueo, self ).save( False )
                    self.parentWindow.init()
                    self.close()
                else:
                    QMessageBox.warning( self, qApp.organizationName(), "No se pudo autorizar el arqueo" )
        except UserWarning as inst:
            if not self.editmodel.observations == "":
                if QMessageBox.question( self, qApp.organizationName(), unicode( inst ) + u"\n¿Desea Continuar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes:
                    dlgUser = dlgSmallUserLogin()
                    if dlgUser.exec_() == QDialog.Accepted:
                        if dlgUser.user.valid and dlgUser.user.hasRole( 'gerencia' ):
                            self.editmodel.authorizationId = dlgUser.user.uid
                            super( FrmArqueo, self ).save( False )
                            self.parentWindow.init()
                            self.close()
                        else:
                            QMessageBox.warning( self,
                                                 qApp.organizationName(),
                                                 "No se pudo autorizar "
                                                 + "el arqueo" )
            else:
                QMessageBox.warning( self,
                                     qApp.organizationName(),
                                     unicode( inst )\
                                     + u"\n Por favor especifique el motivo"
                                     + " de la diferencia" )

    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex() ).value( "iddocumento" ).toString()

    def navigate( self, to ):
        """
        Esta funcion se encarga de navegar entro los distintos documentos
        @param to: es una string que puede tomar los valores 'next' 'previous' 'first' 'last'
        """
        if self.mapper.currentIndex != -1:
            row = self.mapper.currentIndex()
            if to == "next":
                row += 1
                if row >= self.navproxymodel.rowCount():
                    row = self.navproxymodel.rowCount() - 1
                self.mapper.setCurrentIndex( row )
            elif to == "previous":
                if row <= 1: row = 0
                else: row = row - 1
                self.mapper.setCurrentIndex( row )
            elif to == "first":
                self.mapper.toFirst()
            elif to == "last":
                self.mapper.toLast()
        else:
            self.mapper.toLast()()

        self.tabledetailsC.resizeColumnsToContents()
        self.tabledetailsC.horizontalHeader().setStretchLastSection( True )
        self.tabledetailsD.resizeColumnsToContents()
        self.tabledetailsD.horizontalHeader().setStretchLastSection( True )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )




    @pyqtSlot( float )
    @if_edit_model
    def on_sbCkD_valueChanged( self, value ):
        self.editmodel.totalCkD = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbCkC_valueChanged( self, value ):
        self.editmodel.totalCkC = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbCardD_valueChanged( self, value ):
        self.editmodel.totalCardD = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbCardC_valueChanged( self, value ):
        self.editmodel.totalCardC = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbDepositD_valueChanged( self, value ):
        self.editmodel.totalDepositD = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbDepositC_valueChanged( self, value ):
        self.editmodel.totalDepositC = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbTransferD_valueChanged( self, value ):
        self.editmodel.totalTransferD = Decimal( str( value ) )

    @pyqtSlot( float )
    @if_edit_model
    def on_sbTransferC_valueChanged( self, value ):
        self.editmodel.totalTransferC = Decimal( str( value ) )
Ejemplo n.º 24
0
class FrmDevolucion( Ui_frmDevoluciones, Base ):
    """
    Formulario para crear nuevas devoluciones
    """
    web = "devoluciones.php?doc="
    def __init__( self, parent = None ):
        """
        Constructor
        """
        super( FrmDevolucion, self ).__init__( parent )



        self.editmodel = None

        self.status = True

#        las acciones deberian de estar ocultas


#        El modelo principal
        self.navmodel = RONavigationModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = QSortFilterProxyModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
#        Este es el modelo con los datos de la tabla para navegar
        self.detailsmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )
        self.detailsproxymodel.setSourceModel( self.detailsmodel )



#        Cargar los modelos en un hilo aparte
        QTimer.singleShot( 0, self.loadModels )



    def addLine( self ):
        """
        Redefiniendo addLine, se supone que en una 
        liquidacion no se pueden añadir lineas
        """
        raise RuntimeError( "Las devoluciones no deben de añadir lineas nuevas" )

    def updateModels( self ):
#        El modelo principal
        self.navmodel = RONavigationModel( self )
#        El modelo que filtra a self.navmodel
        self.navproxymodel = QSortFilterProxyModel( self )
        self.navproxymodel.setSourceModel( self.navmodel )
        self.navproxymodel.setFilterKeyColumn( -1 )
        self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )

#        Este es el modelo con de la tabla con los detalles
        self.detailsmodel = QSqlQueryModel( self )
#        Este es el filtro del modelo anterior
        self.detailsproxymodel = QSortFilterProxyModel( self )
        self.detailsproxymodel.setSourceModel( self.detailsmodel )


        try:

            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo abrir la conexión con la base de datos" )
            query = u"""
             SELECT
                d.iddocumento,
                d.ndocimpreso AS 'Numero de Entrada',
                padre.ndocimpreso AS padre,
                p.nombre as 'Cliente',
                d.observacion,
                d.fechacreacion AS 'Fecha',
                (@subtotald:=(d.total / ( 1 + ( IF( ca.valorcosto IS NOT NULL , ca.valorcosto / 100, 0 ) )) ) ) AS subtotald,
                @subtotald * (IF( ca.valorcosto IS NOT NULL , ca.valorcosto / 100, 0 )  ) AS ivad,
                SUM( axd.costounit ) as costod,
                d.total AS totald,
                tc.tasa,
                c.descripcion AS 'Concepto',
                b.nombrebodega AS 'Bodega'
            FROM documentos d
            JOIN bodegas b ON d.idbodega = b.idbodega
            JOIN conceptos c ON c.idconcepto = d.idconcepto
            JOIN docpadrehijos dpd ON dpd.idhijo = d.iddocumento
            JOIN documentos padre ON dpd.idpadre = padre.iddocumento
            JOIN tiposcambio tc ON d.idtipocambio = tc.idtc
            JOIN personasxdocumento pd ON d.iddocumento=pd.iddocumento
            LEFT JOIN personas p ON p.idpersona=pd.idpersona
            JOIN articulosxdocumento axd ON axd.iddocumento = d.iddocumento
            LEFT JOIN costosxdocumento cxd ON cxd.iddocumento = padre.iddocumento
            LEFT JOIN costosagregados ca ON ca .idcostoagregado = cxd.idcostoagregado
            WHERE d.idtipodoc = %d AND p.tipopersona=%d
            GROUP BY d.iddocumento""" % ( constantes.IDNC, constantes.CLIENTE )

            self.navmodel.setQuery( query )

            self.detailsmodel.setQuery( u"""
            SELECT 
                ad.idarticulo, 
                ad.descripcion as 'Descripción', 
                axd.unidades as 'Cantidad', 
                axd.precioventa as 'Precio de venta',
                axd.unidades * axd.precioventa as Total,
                axd.iddocumento
            FROM articulosxdocumento axd
            JOIN vw_articulosdescritos ad ON axd.idarticulo = ad.idarticulo
            JOIN documentos d ON d.iddocumento = axd.iddocumento 
            WHERE d.idtipodoc = %d
            """ % constantes.IDNC )




            #        Este objeto mapea una fila del modelo self.navproxymodel a los controles

            self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit )
            self.mapper.setModel( self.navproxymodel )
            self.mapper.addMapping( self.txtDocumentNumber, NDOCIMPRESO )
            self.mapper.addMapping( self.txtObservations, OBSERVACION )
            self.mapper.addMapping( self.dtPicker, FECHA )
            self.mapper.addMapping( self.txtClient, CLIENTE, "text" )
            self.mapper.addMapping( self.txtBill, FACTURA, "text" )
            self.mapper.addMapping( self.lblTotal, TOTAL, "text" )
            self.mapper.addMapping( self.lblSubtotal, SUBTOTAL, "text" )
            #self.mapper.addMapping( self.lblCost, COSTO, "text" )
            self.mapper.addMapping( self.lblTaxes, IMPUESTOS, "text" )
            self.mapper.addMapping( self.txtConcept, CONCEPTO, "text" )
            self.mapper.addMapping( self.txtWarehouse, NOMBREBODEGA, "text" )

    #        asignar los modelos a sus tablas
            self.tablenavigation.setModel( self.navproxymodel )
            self.tabledetails.setModel( self.detailsproxymodel )

            self.tablenavigation.setColumnHidden( IDDOCUMENTO, True )
            self.tablenavigation.setColumnHidden( OBSERVACION, True )
            self.tablenavigation.setColumnHidden( SUBTOTAL, True )
            self.tablenavigation.setColumnHidden( IMPUESTOS, True )
            self.tablenavigation.setColumnHidden( TASA, True )
            self.tablenavigation.setColumnHidden( COSTO, True )


            self.tablenavigation.resizeColumnsToContents()
            self.tablenavigation.horizontalHeader().setStretchLastSection( True )

        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) )
            logging.error( unicode( inst ) )
        except Exception as inst:
            logging.critical( unicode( inst ) )
            QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al cargar la lista de devoluciones" )
        finally:
            if self.database.isOpen():
                self.database.close()

    def updateDetailFilter( self, index ):
        self.detailsproxymodel.setFilterRegExp( self.navmodel.record( index ).value( "iddocumento" ).toString() )
        self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT )
        self.tablenavigation.selectRow( self.mapper.currentIndex() )

    def updateLabels( self ):
        self.lblTotal.setText( moneyfmt( self.editmodel.totalD, 4, "US$" ) + " / " + moneyfmt( self.editmodel.totalC, 4, "C$" ) )
        self.lblSubtotal.setText( moneyfmt( self.editmodel.subtotalD, 4, "US$" ) + " / " + moneyfmt( self.editmodel.subtotalC, 4, "C$" ) )
        self.lblTaxes.setText( moneyfmt( self.editmodel.ivaD, 4, "US$" ) + " / " + moneyfmt( self.editmodel.ivaC, 4, "C$" ) )
        #self.lblCost.setText( moneyfmt( self.editmodel.totalCostD, 4, "US$" ) + " / " + moneyfmt( self.editmodel.totalCostC, 4, "C$" ) )

    def setControls( self, status ):
        """
        En esta funcion cambio el estado enabled de todos los items en el formulario
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible( status )
        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )
        self.tabnavigation.setEnabled( status )
        self.actionNew.setVisible( status )
        self.actionGoFirst.setVisible( status )
        self.actionGoPrevious.setVisible( status )
        self.actionGoNext.setVisible( status )
        self.actionGoLast.setVisible( status )
        self.actionPreview.setVisible( status )
        #self.txtDocumentNumber.setReadOnly( status )
        self.txtObservations.setReadOnly( status )
        self.dtPicker.setReadOnly( status )

        self.actionSave.setVisible( not status )
        self.actionCancel.setVisible( not status )

        self.swConcept.setCurrentIndex( 1 if status else 0 )
        if status:

            self.navigate( 'last' )
            self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers )
        else:
            self.txtClient.setText( self.editmodel.clientName )
            self.txtObservations.setPlainText( "" )
            self.lblTotal.setText( "US$0.0000 / C$0.0000" )
            #self.lblCost.setText( "US$0.0000 / C$0.0000" )
            self.lblTaxes.setText( "US$0.0000 / C$0.0000" )
            self.lblSubtotal.setText( "US$0.0000 / C$0.0000" )
            self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers )
            self.tabWidget.setCurrentIndex( 0 )

#            mostrar las columnas para el modeo edicion u ocultar para navegación
        self.tabledetails.setColumnHidden( IDARTICULO, status )
        self.tabledetails.setColumnHidden( IDDOCUMENTOT, status )

    @pyqtSlot( unicode )
    @if_edit_model
    def on_txtDocumentNumber_textEdited( self, string ):
        """
        Slot documentation goes here.
        """
        self.editmodel.printedDocumentNumber = string

    @pyqtSlot( unicode )
    @if_edit_model
    def on_txtnotacredito_textEdited( self, string ):
        """
        Slot documentation goes here.
        """
        self.editmodel.numnotacredito = string


    @pyqtSlot()
    @if_edit_model
    def on_txtObservations_textChanged( self ):
        """
        Slot documentation goes here.
        """
        self.editmodel.observations = self.txtObservations.toPlainText()

    def newDocument( self ):
        """
        Slot documentation goes here.
        """
        query = QSqlQuery()
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise Exception( u"No se pudo establecer una conexión con la base de datos" )

            self.conceptsmodel = QSqlQueryModel()
            self.conceptsmodel.setQuery( """
            SELECT idconcepto, descripcion 
            FROM conceptos 
            WHERE idtipodoc = %d
            """ % constantes.IDNC )

            if self.conceptsmodel.rowCount() == 0:
                raise UserWarning( u"No existen conceptos para devolución" )


            dlgbill = DlgSelectInvoice()
            if dlgbill.exec_() == QDialog.Accepted:
                self.editmodel = DevolucionModel()
                row = dlgbill.tblBills.selectionModel().currentIndex().row()
                self.editmodel.invoiceId = dlgbill.filtermodel.index( 
                                                 row, 0 ).data().toInt()[0]
                self.editmodel.billPrinted = dlgbill.filtermodel.index( 
                                               row, 1 ).data().toString()
                self.editmodel.clientName = dlgbill.filtermodel.index( 
                                                  row, 3 ).data().toString()

                self.editmodel.clientId = dlgbill.filtermodel.index( 
                                            row, 5 ).data().toInt()[0]

                self.editmodel.ivaRate = Decimal( dlgbill.filtermodel.index( 
                                             row, 6 ).data().toString() )
                self.editmodel.ivaRateId = dlgbill.filtermodel.index( 
                                             row, 7 ).data().toInt()[0]

                self.editmodel.exchangeRate = Decimal( dlgbill.filtermodel.index( 
                                                row, 8 ).data().toString() )
                self.editmodel.exchangeRateId = dlgbill.filtermodel.index( 
                                                  row, 9 ).data().toInt()[0]

                self.editmodel.warehouseName = dlgbill.filtermodel.index( 
                                                 row, 10 ).data().toString()
                self.editmodel.warehouseId = dlgbill.filtermodel.index( 
                                               row, 11 ).data().toInt()[0]


                self.editmodel.uid = self.user.uid


                query = QSqlQuery( """
                CALL spConsecutivo(%d,NULL);
                """ % constantes.IDNC )
                if not query.exec_():
                    raise UserWarning( u"No se pudo calcular el numero de la devolución" )
                query.first()
                self.editmodel.printedDocumentNumber = query.value( 0 ).toString()



                query.prepare( """
                SELECT 
                    v.idarticulo, 
                    v.descripcion,
                    facs.costounit,
                    facs.precioventa, 
                    -1*SUM(unidades) as existencia
                FROM articulosxdocumento facs
                JOIN vw_articulosdescritos v ON facs.idarticulo = v.idarticulo
                LEFT JOIN docpadrehijos devs ON devs.idhijo = facs.iddocumento
                WHERE facs.iddocumento = %d OR devs.idpadre = %d
                GROUP BY v.idarticulo
                """ % ( self.editmodel.invoiceId, self.editmodel.invoiceId ) )
                if not query.exec_():
                    raise Exception( "Ocurrio un error en la consulta" )

                while query.next():
                    linea = LineaDevolucion( self.editmodel )
                    linea.itemId = query.value( 0 ).toInt()[0]
                    linea.itemDescription = query.value( 1 ).toString()
                    linea.itemCost = Decimal( query.value( 2 ).toString() )
                    linea.itemPrice = Decimal( query.value( 3 ).toString() )
                    linea.maxquantity = query.value( 4 ).toInt()[0]


                    row = self.editmodel.rowCount()
                    self.editmodel.insertRows( row )

                    self.editmodel.lines[row] = linea


                self.cbConcept.setModel( self.conceptsmodel )
                self.cbConcept.setModelColumn( 1 )
                self.cbConcept.setCurrentIndex( -1 )


                self.tabnavigation.setEnabled( False )
                self.tabWidget.setCurrentIndex( 0 )
                self.tabledetails.setModel( self.editmodel )

                delegate = DevolucionDelegate()
                self.tabledetails.setItemDelegate( delegate )

                self.tabledetails.resizeColumnsToContents()
                self.dtPicker.setDateTime( QDateTime.currentDateTime() )
                self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels )


                self.txtDocumentNumber.setText( self.editmodel.printedDocumentNumber )
                self.txtBill.setText( self.editmodel.billPrinted )
                self.txtWarehouse.setText( self.editmodel.warehouseName )

                self.status = False
        except UserWarning as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                   unicode( inst ) )
            logging.error( unicode( inst ) )
            self.status = True
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                  u"Hubo un error al intentar crear una "\
                                  + "nueva devolución" )
            logging.critical( unicode( inst ) )
            self.status = True
        finally:
            if self.database.isOpen():
                self.database.close()

    @pyqtSlot( "int" )
    def on_cbConcept_currentIndexChanged( self, index ):
        """
        asignar proveedor al objeto self.editmodel
        """
        if not self.editmodel is None:
            self.editmodel.conceptId = self.conceptsmodel.record( index
                                          ).value( "idconcepto" ).toInt()[0]

    @property
    def printIdentifier( self ):
        return self.navmodel.record( self.mapper.currentIndex()
                                      ).value( "iddocumento" ).toString()

    def cancel( self ):
        self.editmodel = None

        self.tablenavigation.setModel( self.navproxymodel )
        self.tabledetails.setModel( self.detailsproxymodel )

        self.txtBill.setText( "" )
        self.txtClient.setText( "" )
        self.txtDocumentNumber.setText( "" )
        self.txtWarehouse.setText( "" )
        self.tabWidget.setCurrentIndex( 1 )
        self.status = True
Ejemplo n.º 25
0
class tbFactura(QTabWidget, Ui_tbFactura):
    """
    Implementacion de la interfaz grafica para facturas
    """
    web = "facturas.php?doc="
    DATE_FORMAT = "dd/MM/yyyy"

    def __init__(self):
        '''
        Constructor
        '''
        super(tbFactura, self).__init__()

        # ESTABLECER LA INTERFAZ AL FORMULARIO
        self.setupUi(self)
        # VALIDADOR DE MODO DE EDICION
        self.readOnly = True
        self.editmodel = None
        #ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana)
        self.categoriesview.headers = [
            "Descripcion", "Precio", "Unidades", "Existencia", "", "", ""
        ]

        # Crear el modelo para cargar catalogo de clientes
        self.clientesModel = QSqlQueryModel()
        # Crear lista de autocompletado para el combo de clientes
        self.clienteCompleter = QCompleter()
        # Modelo que carga el catalogo de productos
        self.existenciaModel = QSqlQueryModel()

        # Establecer todos los controles en modo de edicion
        self.setControls(False)
        # Crear la conexion a la base de datos
        self.database = QSqlDatabase.database()

        self.vistaprevia = False

        # Cargar los modelos del modo de edicion
        self.updateEditModels()
        self.parent = self.parent()

    def newDocument(self):
        """
        activar todos los controles, llenar los modelos necesarios, 
        crear el modelo FacturaModel, aniadir una linea a la tabla
        """
        self.readOnly = False

        if not self.updateEditModels():
            return

        self.status = False
        self.dtPicker.setDate(self.parentWindow.datosSesion.fecha)

    def updateEditModels(self):
        """
        Este metodo actualiza los modelos usados en el modo edición
        """
        resultado = False
        try:
            if not self.database.isOpen():
                if not self.database.open():
                    raise UserWarning( u"No se pudo abrir la conexión "\
                                       + "con la base de datos" )

            self.clientesModel.setQuery("""
                        SELECT idpersona , nombre AS cliente 
                        FROM personas
                        WHERE escliente = 1
                    """)
            self.cbcliente.setModel(self.clientesModel)

            self.cbcliente.setModelColumn(1)
            self.clienteCompleter.setCaseSensitivity(Qt.CaseInsensitive)
            self.clienteCompleter.setModel(self.clientesModel)
            self.clienteCompleter.setCompletionColumn(1)
            self.cbcliente.setCompleter(self.clienteCompleter)

            self.editmodel = FacturaModel()

            #           Cargar el numero de la factura actual
            query = QSqlQuery("""
                        SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d;
                    """ % constantes.IDFACTURA)
            if not query.exec_():
                raise Exception("No se pudo obtener el numero de la factura")
            query.first()

            if query.size() == 0:
                n = 1
            else:

                n = str(int(query.value(0)) + 1)
                self.editmodel.printedDocumentNumber = str(
                    int(query.value(0)) + 1)

            self.lblnumero.setText(n)

            #            if self.clientesModel.rowCount() == 0:
            #                raise UserWarning( "No existen clientes en la"\
            #                                          + " base de datos" )
            #                return

            self.clienteCompleter.setModel(self.clientesModel)

            self.cbcliente.setModel(self.clientesModel)
            self.cbcliente.setCompleter(self.clienteCompleter)

            #        #Crear el delegado con los articulo y verificar si existen articulos
            self.existenciaModel.setQuery(
                QSqlQuery("""
            SELECT
                categoria,
                descripcion,
                precio,
                unidadesxcaja,
                -- cajas,
                100 as cajas,
                idprecioproducto
            FROM vw_articulos
             -- WHERE existencia >0
                    """))
            self.categoriesview.update("""
            SELECT
                categoria,
                descripcion,
                precio,
                unidadesxcaja,
                -- cajas,
                100 as cajas,
                idprecioproducto
            FROM vw_articulos
            WHERE idprecioproducto IS NOT NULL
             -- WHERE existencia >0
                    """)

            self.categoriesview.expandAll()
            self.categoriesview.setColumnHidden(3, True)
            self.categoriesview.setColumnHidden(4, True)

            self.categoriesview.setColumnWidth(0, 150)
            self.categoriesview.setColumnWidth(1, 60)
            self.categoriesview.setColumnWidth(2, 20)

            self.proxyexistenciaModel = SingleSelectionModel()
            self.proxyexistenciaModel.setSourceModel(self.existenciaModel)
            #            self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX )

            if self.proxyexistenciaModel.rowCount() == 0:
                raise UserWarning("No hay articulos en bodega")

            delegate = FacturaDelegate(self.proxyexistenciaModel)

            self.tabledetails.setItemDelegate(delegate)

            self.tabledetails.setModel(self.editmodel)
            self.tabledetails.setColumnHidden(0, True)
            #            self.editmodel.insertRow(1)
            self.editmodel.dataChanged[QModelIndex,
                                       QModelIndex].connect(self.updateLabels)

            self.txtobservaciones.setPlainText("")
            self.dtPicker.setDate(QDate.currentDate().addDays(1))
            self.editmodel.fecha = QDate.currentDate().addDays(1)
            self.cbcliente.setCurrentIndex(-1)
            resultado = True
        except UserWarning as inst:
            logging.error(unicode(inst))
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        finally:
            if self.database.isOpen():
                self.database.close()
        return resultado

    def addActionsToToolBar(self):
        self.actionRefresh = self.createAction(
            text="Actualizar",
            icon=QIcon.fromTheme('view-refresh',
                                 QIcon(":/icons/res/view-refresh.png")),
            slot=self.refresh,
            shortcut=Qt.Key_F5)

        self.toolBar.addActions([
            self.actionNew,
            self.actionRefresh,
            self.actionPreview,
            self.actionPrint,
            self.actionSave,
            self.actionCancel,
        ])
        self.toolBar.addSeparator()
        self.toolBar.addActions([
            self.actionGoFirst, self.actionGoPrevious, self.actionGoLast,
            self.actionGoNext, self.actionGoLast
        ])

    def refresh(self):
        """
        Actualizar los modelos de edición
        """
        if not self.status:
            if QMessageBox.question(
                    self, qApp.organizationName(),
                    u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?",
                    QMessageBox.Yes | QMessageBox.No) == QMessageBox.No:
                return
            self.updateEditModels()
        else:
            if self.updateModels():
                QMessageBox.information(
                    None, "Factura",
                    u"Los datos fueron actualizados con éxito")

    def printDocument1(self):
        html = u""

        date = QDate.currentDate().toString(self.DATE_FORMAT)

        address = Qt.escape("Bario francisco mesa").replace(",", "<br>")
        contact = Qt.escape("Luis Mejia")
        balance = 5000
        html += ("<p align=right><img src=':/logo.png'></p>"
                 "<p> align = right>Greasy hands ltd."
                 "<br>New Lombard Street"
                 "<br>London<br>WC13 4PX<br>%s</p>"
                 "<p>%s</p><p>Dear %s, </p>"
                 "<p>The balance of your account is %s.") % (
                     date, address, contact, QString("$ %L1").arg(
                         float(balance), 0, "f", 2))

        if balance < 0:
            html += (
                "<p><font color =red><b> Please remit the amount owing immediately.</b></font>"
            )
        else:
            html += "We are delighted to have done business with you."

        html += (
            "</p><p>&nbsp;</p><p>"
            "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>"
        )
        transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500),
                        (QDate.currentDate(), -500),
                        (QDate.currentDate(), 500)]
        for date, amount in transactions:
            color, status = "black", "Credit"
            if amount < 0:
                color, status = "red", "Debid"

            html += (
                "<tr>"
                "<td align= right>%s</td>"
                "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>"
                % (date.toString(self.DATE_FORMAT), status, color,
                   QString("$ %L1").arg(float(abs(amount)), 0, "f", 2)))

        html += ("</table></p><p style='page-break-after=always;'>"
                 "We hope to continue doing business with you</p>")

        pdialog = QPrintDialog()
        if pdialog.exec_() == QDialog.Accepted:
            printer = pdialog.printer()
            document = QTextDocument()
            document.setHtml(html)
            document.print_(printer)

    def printDocument2(self):
        dialog = QPrintDialog()
        if not dialog.exec_():
            return
        self.printer = dialog.printer()
        headFormat = QTextBlockFormat()
        headFormat.setAlignment(Qt.AlignLeft)
        headFormat.setTextIndent(self.printer.pageRect().width() - 216)
        bodyFormat = QTextBlockFormat()
        bodyFormat.setAlignment(Qt.AlignJustify)
        lastParaBodyFormat = QTextBlockFormat(bodyFormat)
        lastParaBodyFormat.setPageBreakPolicy(
            QTextFormat.PageBreak_AlwaysAfter)
        rightBodyFormat = QTextBlockFormat()
        rightBodyFormat.setAlignment(Qt.AlignRight)
        headCharFormat = QTextCharFormat()
        headCharFormat.setFont(QFont("Helvetica", 10))
        bodyCharFormat = QTextCharFormat()
        bodyCharFormat.setFont(QFont("Times", 11))
        redBodyCharFormat = QTextCharFormat(bodyCharFormat)
        redBodyCharFormat.setForeground(Qt.red)
        tableFormat = QTextTableFormat()
        tableFormat.setBorder(1)
        tableFormat.setCellPadding(2)

        document = QTextDocument()
        cursor = QTextCursor(document)
        mainFrame = cursor.currentFrame()
        page = 1

        cursor.insertBlock(headFormat, headCharFormat)

        for text in ("Greasy Hands Ltd.", "New Lombard Street", "London",
                     "WC13", QDate.currentDate().toString(self.DATE_FORMAT)):
            cursor.insertBlock(headFormat, headCharFormat)
            cursor.insertText(text)

        cursor.insertBlock(bodyFormat, bodyCharFormat)
        cursor.insertText("Barrio Francisco Meza")

        cursor.insertBlock(bodyFormat)
        cursor.insertBlock(bodyFormat, bodyCharFormat)
        cursor.insertText("Dear Lyuis")
        cursor.insertBlock(bodyFormat)
        cursor.insertBlock(bodyFormat, bodyCharFormat)
        cursor.insertText(
            QString("The balance of your account is $ %L1.").arg(
                float(500.987), 0, "f", 2))

        cursor.insertBlock(bodyFormat, redBodyCharFormat)
        cursor.insertText("Please remit the amount")

        cursor.insertBlock(bodyFormat, bodyCharFormat)
        cursor.insertText("Transaction")

        transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500),
                        (QDate.currentDate(), -500),
                        (QDate.currentDate(), 500)]

        table = cursor.insertTable(len(transactions), 3, tableFormat)

        row = 0
        for date, amount in transactions:
            cellCursor = table.cellAt(row, 0).firstCursorPosition()
            cellCursor.setBlockFormat(rightBodyFormat)
            cellCursor.insertText(date.toString(self.DATE_FORMAT),
                                  bodyCharFormat)

            cellCursor = table.cellAt(row, 1).firstCursorPosition()
            cellCursor.insertText("Credit", bodyCharFormat)

            cellCursor = table.cellAt(row, 2).firstCursorPosition()
            cellCursor.setBlockFormat(rightBodyFormat)

            cellCursor.insertText(
                QString("The balance of your account is $ %L1.").arg(
                    float(amount), 0, "f", 2), redBodyCharFormat)

            row += 1

        cursor.setPosition(mainFrame.lastPosition())
        cursor.insertBlock(bodyFormat, bodyCharFormat)
        cursor.insertText("We hope")
        document.print_(self.printer)

    def printDocument(self):
        dialog = QPrintDialog()
        if not dialog.exec_():
            return
        self.printer = dialog.printer()
        self.imprimir(self.printer)
        self.document.load(self.editmodel)

    def preview(self):
        self.vistaprevia = True
        preview = frmImpresion(self)
        preview.exec_()

    def save(self):
        """
        Guardar el documento actual
        @rtype: bool
        """
        result = False
        try:
            if not self.valid:
                return False

            if QMessageBox.question(
                    self, qApp.organizationName(),
                    u"¿Esta seguro que desea guardar la factura?",
                    QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:

                if not self.database.isOpen():
                    if not self.database.open():
                        raise UserWarning(
                            u"No se pudo conectar con la base de datos")

                self.editmodel.observaciones = self.txtobservaciones.toPlainText(
                )
                if not self.editmodel.save():
                    raise UserWarning("No se ha podido guardar la factura")

                QMessageBox.information(
                    None, qApp.organizationName(),
                    u"""El documento se ha guardado con éxito""")

                self.readOnly = True

                self.updateModels()

                #                self.navigate( 'last' )
                #                self.status = True
                result = True
        except UserWarning as inst:
            logging.error(unicode(inst))
            QMessageBox.critical(self, qApp.organizationName(), unicode(inst))
        except Exception as inst:
            logging.critical(unicode(inst))
            QMessageBox.critical(self, qApp.organizationName(),
                                 u"Hubo un error al guardar la factura")
        finally:
            if self.database.isOpen():
                self.database.close()
        return result

#    @pyqtSlot(QModelIndex)
#    def on_categoriesview_doubleClicked(self,index):

    @pyqtSlot(QModelIndex)
    def on_categoriesview_activated(self, index):
        articulo = self.categoriesview.model().asRecord(index)
        if len(articulo) > 0:
            nuevo = True

            for i, line in enumerate(self.editmodel.lines):
                if line.itemId == articulo[5]:
                    nuevo = False
                    fila = i
                    line = self.editmodel.lines[self.editmodel.rowCount() - 1]

            if nuevo:
                fila = self.editmodel.rowCount()
                self.editmodel.insertRow(fila)
                self.parent.saveAct.setEnabled(True)
                linea = self.editmodel.lines[fila]
                linea.itemDescription = articulo[0] + " " + articulo[1]
                linea.itemPrice = Decimal(articulo[2])
                linea.itemId = articulo[5]

                linea.quantityperbox = int(articulo[3])

            self.editmodel.lines[fila].quantity += 1
            self.editmodel.lines[fila].existencia = int(
                articulo[4]) - self.editmodel.lines[fila].quantity
            indice = self.editmodel.index(fila, 2)
            self.editmodel.dataChanged.emit(indice, indice)
            indice = self.editmodel.index(fila, 3)
            self.editmodel.dataChanged.emit(indice, indice)
            indice = self.editmodel.index(fila, 5)
            self.editmodel.dataChanged.emit(indice, indice)

    @pyqtSlot()
    def on_btneditar_clicked(self):
        articulo = dlgArticulo(self)
        articulo.exec_()
        self.updateEditModels()

    @pyqtSlot(int)
    def on_cbcliente_currentIndexChanged(self, index):
        """
        asignar proveedor al objeto self.editmodel
        """
        if self.editmodel is not None:
            numero = self.clientesModel.record(index).value("idpersona")
            self.editmodel.clienteId = int(numero) if numero is not None else 0

    @pyqtSlot(unicode)
    def on_cbcliente_editTextChanged(self, text):
        """
        asignar proveedor al objeto self.editmodel
        """
        if self.editmodel is not None:
            self.editmodel.cliente = str(text)

    @pyqtSlot(int)
    def on_cbvendedor_currentIndexChanged(self, index):
        """
        asignar proveedor al objeto self.editmodel
        """
        self.editmodel.vendedorId = self.vendedoresModel.record(index).value(
            "idpersona").toInt()[0]

    @pyqtSlot(QDate)
    def on_dtPicker_dateChanged(self, date):
        if self.editmodel is not None:
            self.editmodel.fecha = date

    @pyqtSlot(bool)
    def on_rbcontado_toggled(self, on):
        """
        Asignar las observaciones al objeto editmodel
        """
        self.editmodel.escontado = 1 if on else 0

    def on_txtSearch_textChanged(self, text):
        """
        Cambiar el filtro de busqueda
        """
        self.filtermodel.setFilterRegExp(text)

    def setControls(self, status):
        """
        @param status: false = editando        true = navegando
        """
        #        self.actionPrint.setVisible( status )
        self.readOnly = status
        self.txtobservaciones.setReadOnly(status)
        #        self.actionPreview.setVisible( status )
        #        self.actionAnular.setVisible( status )
        #        self.toolBar.setVisible(status)

        #        self.lblnfac.setText( self.editmodel.printedDocumentNumber )
        self.swcliente.setCurrentIndex(0)
        self.lbltotal.setText("C$ 0.00")
        self.tabledetails.setEditTriggers(QAbstractItemView.AllEditTriggers)
        #        self.lblanulado.setHidden( True )

        self.tabledetails.horizontalHeader().setStretchLastSection(True)

        self.tabledetails.setColumnHidden(IDARTICULO, True)
        self.tabledetails.setColumnHidden(IDDOCUMENTOT, True)

    def updateLabels(self):
        self.lbltotal.setText(moneyfmt(self.editmodel.total, 2, "C$ "))

    @property
    def valid(self):
        """
        Un documento es valido cuando 
        self.printedDocumentNumber != ""
        self.providerId !=0
        self.validLines >0
        self.ivaId !=0
        self.uid != 0
        self.warehouseId != 0
        """
        if int(self.editmodel.clienteId) == 0 and self.editmodel.cliente == "":
            QMessageBox.warning(self, qApp.organizationName(),
                                "Por favor elija el cliente")
            self.cbcliente.setFocus()

        elif self.editmodel.rowCount() == 0:
            QMessageBox.warning(
                self, qApp.organizationName(),
                "Por favor agregue algun articulo a la factura")
        else:
            return True
        return False

    def imprimir(self, printer):

        leftMargin = 72
        widthCol = 100

        arialFont = QFont("Helvetica", 16, 3)

        fuente = QFontMetrics(arialFont)
        arialLineHeight = fuente.height()

        fondo = QPixmap(":/images/res/fondo.png")
        painter = QPainter(printer)
        pageRect = printer.pageRect()
        page = 1

        painter.save()
        if self.vistaprevia:
            painter.drawPixmap(0, 0, 530, 830, fondo)

        painter.setFont(arialFont)

        y = 180
        x = 35
        painter.drawText(x, y, self.editmodel.fecha.toString("dd   MM   yy"))

        y = 210
        x = 85

        painter.drawText(x, y, self.editmodel.cliente)

        painter.setFont(arialFont)

        cajasFont = QFont("Helvetica", 10, 2)
        x = -5
        y = 295

        painter.setFont(cajasFont)
        painter.drawText(x, y - arialLineHeight - 1, "Cajas")

        for row in self.editmodel.lines:
            painter.setFont(cajasFont)
            x = 2
            painter.drawText(x, y, row.cantidad())

            painter.setFont(arialFont)
            total = moneyfmt(row.total, 2, "")
            x = 470 - fuente.width(total)
            painter.drawText(x, y, total)

            x = 310
            painter.drawText(x, y, moneyfmt(row.itemPrice, 2, ""))

            x = 30
            painter.drawText(x, y, row.unidades())

            x = 80
            painter.drawText(x, y, row.itemDescription)

            y += arialLineHeight

        total = moneyfmt(self.editmodel.total, 2, "")
        y = 690
        x = 470 - fuente.width(total)
        painter.drawText(x, y, total)

        painter.setPen(Qt.black)
        #        printer.newPage()
        painter.restore()