Ejemplo n.º 1
0
    def updateArticles( self ):
        """
        Actualizar la lista de articulos
        """
        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" )



            self.updateArticleList( query )
            self.editmodel.updateLines( query )


            providers_model = QSqlQueryModel()
            providers_model.setQuery( """
            SELECT idpersona, nombre 
            FROM personas p 
            WHERE tipopersona = 2 AND activo = 1
            """ )
            if not providers_model.rowCount() > 0:
                raise UserWarning( "No existen proveedores en el sistema" )
            self.cbProvider.setModel( providers_model )
            self.cbProvider.setModelColumn( 1 )

            warehouse_model = QSqlQueryModel()
            warehouse_model.setQuery( """
            SELECT idbodega, nombrebodega
            FROM bodegas b
            ORDER BY idbodega
            """ )
            if not warehouse_model.rowCount() > 0:
                raise UserWarning( "No existen bodegas en el sistema" )
            self.cbWarehouse.setModel( warehouse_model )
            self.cbWarehouse.setModelColumn( 1 )

            self.cbWarehouse.setCurrentIndex( -1 )
            self.cbProvider.setCurrentIndex( -1 )



        except UserWarning as inst:
            QMessageBox.warning( self, qApp.organizationName(),
                                  unicode( inst ) )
            logging.error( query.lastError().text() )
            logging.error( unicode( inst ) )
            self.cancel()
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                "Hubo un error fatal al tratar de actualizar la lista " \
                + "de articulos, el sistema no puede recuperarse" \
                + " y sus cambios se han perdido" )
            logging.error( query.lastError().text() )
            logging.critical( unicode( inst ) )
            self.cancel()
Ejemplo n.º 2
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
 def get_linked_esu_list(self, usrn):
     """
     function that selects all esus for a determined street
     :param usrn: the unique identifier of a certain street
     :return: list[esu_ids] all esu ids linked to a certain street or
     void in case a street does not have any linked esu
     """
     # executing the query
     esus_query_model = QSqlQueryModel()
     esus_query_model.setQuery(self.queries[9].format(usrn))
     while esus_query_model.canFetchMore():
         esus_query_model.fetchMore()
     n_rows = esus_query_model.rowCount()
     # skip if no esus are linked
     if n_rows == 0:
         return
     else:
         i = 0
         esus_list = []
         # creating a list of ESUs Ids that are linked to the street
         while i <= n_rows - 1:
             model_index = esus_query_model.createIndex(i, 0)
             esu = model_index.data()
             esus_list.append(esu)
             i += 1
         return esus_list
Ejemplo n.º 4
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.º 5
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.º 6
0
 def setQuery(self,  str,  db=None):
     if db == None:
         self.query = QSqlQuery(str)
     else:
         self.query = str
     QSqlQueryModel.setQuery(self,  str)
     del self.data
     self.data = []
     self.rCount = QSqlQueryModel.rowCount(self)
     if self.rCount > 10000:
         self.rCount = 10000
     self.cCount = QSqlQueryModel.columnCount(self)
     for i in range(self.rCount ):
         row = []
         for j in range(self.cCount):
             row.append(QSqlQueryModel.data(self, QSqlQueryModel.index(self, i, j)))
         self.data.append(row)
     self.clear()
     print self.rowCount(), self.columnCount()
Ejemplo n.º 7
0
 def setQuery(self, str, db=None):
     if db == None:
         self.query = QSqlQuery(str)
     else:
         self.query = str
     QSqlQueryModel.setQuery(self, str)
     del self.data
     self.data = []
     self.rCount = QSqlQueryModel.rowCount(self)
     if self.rCount > 10000:
         self.rCount = 10000
     self.cCount = QSqlQueryModel.columnCount(self)
     for i in range(self.rCount):
         row = []
         for j in range(self.cCount):
             row.append(
                 QSqlQueryModel.data(self, QSqlQueryModel.index(self, i,
                                                                j)))
         self.data.append(row)
     self.clear()
     print self.rowCount(), self.columnCount()
Ejemplo n.º 8
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.º 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)
 def check_start_end(self, tol):
     # set the feature counter to 0
     count = 0
     # initialises two virtual objects points (start and end point)
     start_point = self.start_point
     end_point = self.end_point
     # uses the qgis python api to access the ESU Graphic Layer
     esu_layer = self.esu_layer
     # runs the query number 8 to retrieve all streets from the Database
     streets_model = QSqlQueryModel()
     streets_model.setQuery(self.queries[8])
     while streets_model.canFetchMore():
         streets_model.fetchMore()
     n_columns = streets_model.columnCount()
     n_rows = streets_model.rowCount()
     i = 0
     j = 0
     # first loop start (for each street):
     start_end_content = []
     while i <= n_rows - 1:
         self.progress_win.setLabelText("Checking start-end Coordinates...")
         # initialises the state of the checks booleans both to false
         start_ok = False
         end_ok = False
         col_info = []
         while j <= n_columns - 1:
             model_index = streets_model.createIndex(i, j)
             if j == 0:
                 data = model_index.data()
                 col_info.append(data)
             if j == 1:
                 data = model_index.data()
                 col_info.append(data)
             if j == 2:
                 data = model_index.data()
                 col_info.append(data)
             if j >= 3:
                 data = model_index.data()
                 col_info.append(data)
             j += 1
         usrn = col_info[0]
         ref_type = col_info[2]
         desc = col_info[1]
         start_point.set(float(col_info[3]), float(col_info[4]))
         end_point.set(float(col_info[5]), float(col_info[6]))
         # filter the layer "ESU Graphic" for the ESUs Ids returned from the list
         # deal just with the arcs part of multi arcs street
         esus_list = self.get_linked_esu_list(usrn)
         feat_filter = self.build_layer_filter(esus_list)
         feat_request = QgsFeatureRequest()
         feat_request.setFilterExpression(feat_filter)
         # second loop starts (for each arc (ESU) composing the street)
         # iterate through all filtered features and their proximity with the start and end of the street
         features = self.esu_layer.getFeatures(feat_request)
         features.rewind()
         # iterates through features
         for feat in features:
             # check start end points for each of the only if none of the start end points of
             # a ESU on each street is not already matched
             if (start_ok is not True) or (end_ok is not True):
                 result = self.start_end_proximity(start_point, end_point,
                                                   feat, tol)
                 # both dist are ok
                 if result == 3:
                     start_ok = True
                     end_ok = True
                 # just end dist is ok
                 elif result == 2:
                     end_ok = True
                 # just start dist is ok
                 elif result == 1:
                     start_ok = True
             else:
                 break
         # in case of problems
         if not start_ok or not end_ok:
             count += 1
             start_end_item = [str(col_info[0]) + ","]
             # handles the creation of the report on a text file
             if not start_ok and not end_ok:
                 start_end_item.append("(both),")
             if not start_ok and end_ok:
                 start_end_item.append("(start),")
             if start_ok and not end_ok:
                 start_end_item.append("(end),")
             start_end_item.append(str(ref_type) + ",")
             start_end_item.append(str(desc) + "\n")
             start_end_content.append(start_end_item)
         j = 0
         i += 1
     if count == 0:
         self.progress_win.setValue(7)
         return
     else:
         start_end_content.insert(0, self.column_names[5])
         self.progress_win.setValue(7)
         return self.content_to_screen(content_list=start_end_content,
                                       query_model=None,
                                       columns_name_id=None,
                                       no_content_id=8)
Ejemplo n.º 11
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.º 12
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.º 13
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.º 14
0
    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" )

            query.prepare( """
                SELECT idtc 
                FROM tiposcambio 
                LIMIT 1
                """ )
            query.exec_()
            if not query.first():
                raise UserWarning( u"No existen tipos de cambio en "
                                   + "la base de datos" )

            self.editmodel = LiquidacionModel( self.user.uid )
            self.editmodel.applyISO = self.ckISO.isChecked()
            self.addLine()
            query.prepare( """
            SELECT 
                c.idcostoagregado,
                valorcosto,
                factorpeso,
                idtipocosto 
            FROM costosagregados c 
            LEFT JOIN tsim t ON c.idcostoagregado=t.idtsim 
            WHERE activo=1 AND idtipocosto IN (%d,%d,%d,%d)
            LIMIT 4
            """ % ( constantes.IVA,
                    constantes.SPE,
                    constantes.TSIM,
                    constantes.ISO ) )
            if not query.exec_():
                raise UserWarning( "No se pudo ejecutar la consulta para "
                                   + "obtener los valores de los impuestos" )
            elif not query.size() == 4:
                raise UserWarning( "No se pudieron obtener los valores "
                                   + "de los impuestos" )
#TODO: Deberian acaso los valores de iva, spe, tsim, iso cambiar 
#cuando cambie la fecha???            
            while query.next():
                if query.value( 3 ).toInt()[0] == 1: #IVA
                    self.editmodel.ivaId = query.value( 0 ).toInt()[0]
                    self.editmodel.ivaRate = Decimal( query.value( 1 ).toString() )
                elif query.value( 3 ).toInt()[0] == 4: #SPE
                    self.editmodel.speId = query.value( 0 ).toInt()[0]
                    self.editmodel.speTotal = Decimal( query.value( 1 ).toString() )
                elif query.value( 3 ).toInt()[0] == 5: #TSIM
                    self.editmodel.tsimId = query.value( 0 ).toInt()[0]
                    self.editmodel.tsimRate = Decimal( query.value( 1 ).toString() )
                    self.editmodel.weightFactor = Decimal( query.value( 2 ).toString() )
                elif query.value( 3 ).toInt()[0] == 6: #ISO
                    self.editmodel.isoId = query.value( 0 ).toInt()[0]
                    self.editmodel.isoRate = Decimal( query.value( 1 ).toString() )

            providersModel = QSqlQueryModel()
            providersModel.setQuery( """
            SELECT 
                idpersona, 
                nombre
            FROM personas p
            WHERE tipopersona = %d AND activo = 1
            """ % constantes.PROVEEDOR )
            if not providersModel.rowCount() > 0:
                raise UserWarning( "No existen proveedores en el sistema" )
            self.cbProvider.setModel( providersModel )
            self.cbProvider.setModelColumn( 1 )

            warehouseModel = QSqlQueryModel()
            warehouseModel.setQuery( """
            SELECT 
                idbodega, 
                nombrebodega 
            FROM bodegas b
            ORDER BY idbodega  
            """ )
            if not warehouseModel.rowCount() > 0:
                raise UserWarning( "No existen bodegas en el sistema" )
            self.cbWarehouse.setModel( warehouseModel )
            self.cbWarehouse.setModelColumn( 1 )

            self.editdelegate = LiquidacionDelegate()
            self.updateArticleList( query )
            if self.editdelegate.prods.rowCount() == 0:
                raise UserWarning( u"El sistema no tiene registrado ningún "
                                   + u"tipo de articulo, por favor añada "
                                   + u"articulos antes de hacer una "
                                   + u"liquidación" )




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

            self.tabledetails.setItemDelegate( self.editdelegate )
            self.tabledetails.setEditTriggers( QAbstractItemView.EditKeyPressed
                                            | QAbstractItemView.AnyKeyPressed
                                             | QAbstractItemView.DoubleClicked )




            self.accountseditdelegate = 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 != %s
            """ % movimientos.INVENTARIO ), True )

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



            self.tabletotals.setModel( self.editmodel.totalsModel )
            self.tabledetails.setColumnHidden( IDDOCUMENTOT, False )

            self.tableaccounts.setModel( None )
            self.tabledetails.setColumnWidth( DESCRIPCION, 250 )



            self.status = 2

        except UserWarning as inst:
            self.status = 1
            QMessageBox.critical( self,
                                  qApp.organizationName(), unicode( inst ) )
            logging.error( inst )
        except Exception as inst:
            QMessageBox.critical( self, qApp.organizationName(),
                                  u"Hubo un error al intentar iniciar "
                                  + u"una nueva liquidación" )
            self.status = 1
            logging.critical( inst )
        finally:
            if self.database.isOpen():
                self.database.close()
Ejemplo n.º 15
0
    def results_to_txt_row(self, vals, sql, mode):
        query_model = QSqlQueryModel()
        query_model.setQuery(sql)
        model_index = QModelIndex()
        row_count = query_model.rowCount(model_index)
        if row_count < 1:
            self.file.write(self.no_content)
        else:
            query = QSqlQuery(self.db)
            query.exec_(sql)
            rec = query.record()
            if mode == "streets":
                avals = [
                    rec.indexOf(vals[0]),
                    rec.indexOf(vals[1]),
                    rec.indexOf(vals[2]),
                    rec.indexOf(vals[3]),
                    rec.indexOf(vals[4]),
                    rec.indexOf(vals[5]),
                    rec.indexOf(vals[6]),
                    rec.indexOf(vals[7]),
                    rec.indexOf(vals[8]),
                    rec.indexOf(vals[9]),
                    rec.indexOf(vals[10]),
                    rec.indexOf(vals[11])
                ]
                n = 0
                # write content
                headers = self.headers[0]
                while n <= len(headers) - 1:
                    if n == len(headers) - 1:
                        self.file.write(str(headers[n]) + "\n")
                    else:
                        self.file.write(str(headers[n]) + " ")
                    n += 1
                while query.next():
                    line = [
                        query.value(avals[0]),
                        query.value(avals[1]),
                        query.value(avals[2]),
                        query.value(avals[3]),
                        query.value(avals[4]),
                        query.value(avals[5]),
                        query.value(avals[6]),
                        query.value(avals[7]),
                        query.value(avals[8]),
                        query.value(avals[9]),
                        query.value(avals[10]),
                        query.value(avals[11])
                    ]

                    self.file.write(
                        str(line[0]) + " , " + str(line[1]) + " , " +
                        str(line[2]) + " , " + str(line[3]) + " , " +
                        str(line[4]) + " , " + str(line[5]) + " , " +
                        self.format_dates(str(line[6])) + " , " +
                        self.format_dates(str(line[7])) + " , " +
                        self.format_dates(str(line[8])) + " , " +
                        self.format_dates(str(line[9])) + " , " +
                        str(line[10]) + " " + str(line[11]) + "\n")
            else:
                avals = [
                    rec.indexOf(vals[0]),
                    rec.indexOf(vals[1]),
                    rec.indexOf(vals[2]),
                    rec.indexOf(vals[3]),
                    rec.indexOf(vals[4]),
                    rec.indexOf(vals[5]),
                    rec.indexOf(vals[6]),
                    rec.indexOf(vals[7])
                ]
                m = 0
                headers = self.headers[1]
                while m <= len(headers) - 1:
                    if m == len(headers) - 1:
                        self.file.write(str(headers[m]) + "\n")
                    else:
                        self.file.write(str(headers[m]) + " ")
                    m += 1
                while query.next():
                    line = [
                        query.value(avals[0]),
                        query.value(avals[1]),
                        query.value(avals[2]),
                        query.value(avals[3]),
                        query.value(avals[4]),
                        query.value(avals[5]),
                        query.value(avals[6]),
                        query.value(avals[7])
                    ]
                    self.file.write(
                        str(line[0]) + " , " + str(line[1]) + " , " +
                        str(line[2]) + " , " + str(line[3]) + " , " +
                        str(line[4]) + " , " + str(line[5]) + " , " +
                        str(line[6]) + " , " + str(line[7]) + "\n")
Ejemplo n.º 16
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.º 17
0
    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
Ejemplo n.º 18
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.º 19
0
class FrmCierreContable( Ui_frmCierreContable, QMainWindow ):
    """
    Implementación de la interfaz cierre contable
    """
    def __init__( self, parent,tipocierre ):
        super( FrmCierreContable, self ).__init__( parent )
        self.setupUi( self )
        self.parentWindow = parent

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

        self.navproxymodel.setFilterKeyColumn( -1 )
        self.navproxymodel.setFilterCaseSensitivity ( Qt.CaseInsensitive )
        self.editmodel = None
        self.fecha = None
        self.status = True
        self.tipocierre=tipocierre
        self.validomensual=None
        self.validoanual=None
        
        self.dtPicker.setMaximumDate( QDate.currentDate() )
        self.dtPicker.setDate( QDate.currentDate() )
        
        self.lbltitulo.setText(self.lbltitulo.text()+" "+self.tipocierre)
        if self.tipocierre=="Anual":
            self.dtPicker.setDisplayFormat("yyyy")        
    @pyqtSlot( QDate )
    def on_dtPicker_dateChanged( self, date ):
        """
        Asignar la fecha al objeto __document
        """
        self.fecha = date
        self.updateModels()

    def updateModels( self):
        try:
            if not QSqlDatabase.database().isOpen():
                if not QSqlDatabase.database().open():
                    raise UserWarning( "No se pudo conectar con la base de datos" )
            query = QSqlQuery()
            if self.tipocierre=="Mensual":         
                'Lista de documentos para cierre mensual'
                q = u"""
                SELECT
                    iddocumento,
                    ndocimpreso as 'No. Documento',
                    td.descripcion as TipoDocumento,
                    format(total ,4)as Total,
                    date_format(fechacreacion,'%s') as Fecha,
                    observacion as Observaciones,
                    estados.descripcion as Estado
                FROM documentos d
                JOIN estadosdocumento estados ON estados.idestado=d.idestado
                JOIN tiposdoc td ON d.idtipodoc=td.idtipodoc
                WHERE MONTH(d.fechacreacion)= %s  AND d.idtipodoc!=%d and d.idtipodoc!= %d
                """ % ( "%d/%m/%Y", self.fecha.toString( "MM" ), +constantes.IDAPERTURA , constantes.IDCIERREMENSUAL )
        
                self.navmodel.setQuery( q )  
                   
            else:
                q=u"""
                SELECT 
                    iddocumento,
                    ndocimpreso as 'No. Documento',
                    td.descripcion as TipoDocumento,
                    format(total ,4)as Total,
                    date_format(fechacreacion,'%s') as Fecha,
                    observacion as Observaciones,
                    estados.descripcion as Estado
                FROM documentos d
                JOIN estadosdocumento estados ON estados.idestado=d.idestado
                JOIN tiposdoc td ON d.idtipodoc=td.idtipodoc
                WHERE d.idtipodoc=%d  
                AND YEAR(d.fechacreacion)=%s""" %("%d/%m/%Y",constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))              
                self.navmodel.setQuery( q )            
            
            'Verifico si hay documentos'
            if self.navmodel.rowCount() == 0:
                self.toolBar.removeAction( self.actionSave )
            else:
                self.toolBar.addActions( [
                self.actionSave] )
                self.actionSave.triggered.connect( self.save )
    
            self.tabledetails.setModel( self.navproxymodel )
            self.tabledetails.setColumnHidden( 0, True )
            self.tabledetails.resizeColumnsToContents()
        
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.applicationName(), unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.critical( self, qApp.organizationName(),
                                   u"Hubo un error al actualizar la tabla" )

    def validarCierreAnual(self):
        try:
            query=QSqlQuery()
            q=u"""
            SELECT d.iddocumento 
            FROM documentos d 
            WHERE d.idtipodoc=%d  
            AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))
            query.prepare(q)
            
            if not query.exec_():
                raise Exception( "No se pudo ejecutar la consulta para determinar si se cerraron todos los meses del año" )
            
            if query.size()<12 and query.size()>0:
                raise UserWarning( "No se han cerrado todos los meses del Ejercicio" )
            return True
            
        except UserWarning as inst:
            logging.error( unicode( inst ) )
            QMessageBox.critical( self, qApp.applicationName(), unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            return False
            
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.warning( self,
             qApp.organizationName(),unicode(inst))
            return False   

    def validarCierreMensual(self):
        try:
            query=QSqlQuery()
            q=u"""
                SELECT d.iddocumento 
                FROM documentos d 
                WHERE d.idtipodoc=%d  
                AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,self.fecha.toString( "yyyy" ))
            query.prepare(q)
            
            if not query.exec_():
                raise UserWarning( "No se pudo ejecutar la consulta para determinar si existe algun cierre en el año" )         
            if query.size()>0:
                mes=self.fecha.addMonths(-1)             
                q=u"""
                    SELECT d.iddocumento 
                    FROM documentos d 
                    WHERE d.idtipodoc=%d 
                    AND MONTH(fechacreacion)=%s 
                    AND YEAR(d.fechacreacion)=%s""" %(constantes.IDCIERREMENSUAL,mes.toString( "MM"),self.fecha.toString( "yyyy" ))
                query.prepare(q)
                
                if not query.exec_():
                    raise UserWarning( "No se pudo ejecutar la consulta para determinar si se cerro el mes anterior" )         
                if query.size()==0:
                    raise UserWarning( "No se ha cerrado el mes anterior" )        
            
                  
            #Verifico si existe un cierre para el mes en proceso
            q = """
            SELECT
                d2.iddocumento
            FROM documentos d
            JOIN docpadrehijos dp ON d.iddocumento=dp.idpadre
            JOIN documentos d2 ON d2.iddocumento=dp.idhijo
            WHERE d2.idtipodoc=%d and month(d2.fechacreacion)=%s
            LIMIT 1
            """ % ( constantes.IDCIERREMENSUAL, self.fecha.toString( "MM" ) )
            
            query.prepare( q )
            
            if not query.exec_():
                raise UserWarning( "No se pudo ejecutar la consulta para "\
                                   + "verificar si existe un cierre contable" )
            
            #El mes actual no se puede cerrar
            
            hoy=QDate.currentDate()
            if self.fecha.month()==hoy.month() and self.fecha.year() == hoy.year():
                raise UserWarning( "No se puede cerrar el mes en proceso" )
    
            return True
        
        except Exception as inst:
            logging.critical( unicode( inst ) )
            self.toolBar.removeAction( self.actionSave )
            QMessageBox.warning( self,
             qApp.organizationName(),unicode(inst))
             
        return False
               
    def save( self ):
        if QMessageBox.question( self, qApp.organizationName(),
                                u"¿Esta seguro que desea hacer este cierre "+self.tipocierre+"?\n"\
                                + u"Esta accion no se puede deshacer",  
                                 QMessageBox.Ok | QMessageBox.No ) == QMessageBox.Ok:
            docpendientes = True
            for i in range( self.navproxymodel.rowCount() ):
                if self.navproxymodel.index( i, ESTADO ).data( Qt.EditRole ).toString() != "CONFIRMADO" and self.navproxymodel.index( i, ESTADO ).data( Qt.EditRole ).toString() != "ANULADO":
                    docpendientes = False
            if self.tipocierre=="Mensual":
                if docpendientes == False or self.validarCierreMensual()==False:
                    QMessageBox.warning( self,
                        qApp.organizationName(),
                         u"No se realizó el cierre contable Mensual ")
                else:
                    self.saveMensual()                                     
            else: 
                if docpendientes==False or self.validarCierreAnual()==False:
                    QMessageBox.warning( self,
                     qApp.organizationName(),
                     u"No se realizó el cierre contable Anual ")
                else:
                    self.saveAnual()
    def saveAnual(self):
        pass
                
    def saveMensual(self):
        query = QSqlQuery()
        try:
            query.prepare( """
            CALL `spCierreMensual`(:IDCIERRE,
            :MES,
            :ESTADO,
            :ANO,
            :INGRESOSXVENTA,
            :OTROSINGRESOS,
            :COSTOSGASTOSOPERACIONES,
            :GASTOSXVENTAS,
            :GASTOS,
            :GASTOSFINANCIEROS,
            :PRODUCTOSFINANCIEROS,
            :OTROSGASTOS,
            :PERDIDASGANANCIAS)
            """ )
            query.bindValue( ":IDCIERRE", constantes.IDCIERREMENSUAL )
            query.bindValue( ":MES", self.fecha.toString( "MM" ) )
            query.bindValue( ":ESTADO", constantes.CONFIRMADO )
            query.bindValue( ":ANO", self.fecha.toString( "yyyy" ) )
            query.bindValue( ":INGRESOSXVENTA",
                             constantes.INGRESOSXVENTA )
            query.bindValue( ":OTROSINGRESOS",
                             constantes.OTROSINGRESOS )
            query.bindValue( ":COSTOSGASTOSOPERACIONES",
                              constantes.COSTOSGASTOSOPERACIONES )
            query.bindValue( ":GASTOSXVENTAS",
                              constantes.GASTOSXVENTAS )
            query.bindValue( ":GASTOS", constantes.GASTOS )
            query.bindValue( ":GASTOSFINANCIEROS",
                             constantes.GASTOSFINANCIEROS )
            query.bindValue( ":PRODUCTOSFINANCIEROS",
                              constantes.PRODUCTOSFINANCIEROS )
            query.bindValue( ":OTROSGASTOS", constantes.OTROSGASTOS )
            query.bindValue( ":PERDIDASGANANCIAS",
                             constantes.PERDIDASGANANCIAS )
            if not query.exec_():
                raise UserWarning( "No se pudo cerrar el mes contable" )

            self.toolBar.removeAction( self.actionSave )
#                self.toolBar.addActions( self.actionPrint )
#                self.actionPrin.triggered.connect( self.printPreview )

        except UserWarning as inst:

            logging.error( inst )
            logging.error( query.lastError().text() )
            QMessageBox.critical( self, qApp.organizationName(),
                                  unicode( inst ) )
Ejemplo n.º 20
0
class SrwrLookup:
    def __init__(self, iface, db, srwr_lu_dia):
        self.iface = iface
        self.db = db
        self.srwr_lu_dia = srwr_lu_dia
        self.connect_buttons()
        self.items_model = None
        self.data_model = None
        self.queries = {
            0:
            """SELECT designation_code,
                  (designation_code || ' : ' || designation_text) AS 'display'
                  FROM tlkpSPEC_DES
                  ORDER BY designation_code""",
            1:
            """SELECT reinstatement_code,
                  (reinstatement_code || ' : ' || description) AS 'display'
                  FROM tlkpREINS_CAT
                  ORDER BY reinstatement_code""",
            2:
            """SELECT road_status_ref,
                  (road_status_ref || ' : ' || Description) AS 'display'
                  FROM tlkpROAD_STATUS
                  ORDER BY road_status_ref"""
        }
        self.tables = {
            0: "tlkpSPEC_DES",
            1: "tlkpREINS_CAT",
            2: "tlkpROAD_STATUS"
        }
        self.columns = {
            0: "designation_code",
            1: "reinstatement_code",
            2: "road_status_ref"
        }
        self.amend_queries = {
            0:
            """UPDATE tlkpSPEC_DES SET designation_text = '{0}'
                  WHERE designation_code = {1} """,
            1:
            """UPDATE tlkpREINS_CAT SET description = '{0}'
                  WHERE reinstatement_code = {1} """,
            2:
            """UPDATE tlkpROAD_STATUS SET Description = '{0}'
                  WHERE road_status_ref = {1}"""
        }
        self.changes_made = False
        # Setup initial view
        self.srwr_lu_dia.ui.desRadioButton.setChecked(True)
        self.populate_list(0)

    def connect_buttons(self):
        """
        events handler for buttons in the form
        :return: object
        """
        self.srwr_lu_dia.ui.addButton.clicked.connect(self.add_lookup)
        self.srwr_lu_dia.ui.removeButton.clicked.connect(self.remove_lookup)
        self.srwr_lu_dia.ui.amendButton.clicked.connect(self.amend_lookup)
        self.srwr_lu_dia.ui.closeButton.clicked.connect(self.close_browser)
        self.srwr_lu_dia.ui.desRadioButton.pressed.connect(
            lambda: self.populate_list(0))
        self.srwr_lu_dia.ui.reinsRadioButton.pressed.connect(
            lambda: self.populate_list(1))
        self.srwr_lu_dia.ui.statRadioButton.pressed.connect(
            lambda: self.populate_list(2))
        self.srwr_lu_dia.ui.itemsListView.pressed.connect(
            lambda: self.selection_handler())

    def close_browser(self):
        # close the dialog window
        if self.changes_made:
            changes_made_msg_box = QMessageBox(
                QMessageBox.Information, " ", "SRWR lookup tables updated.\n\n"
                "Restart roadNet to populate menus with new values.",
                QMessageBox.Ok, None)
            changes_made_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                | Qt.WindowTitleHint)
            changes_made_msg_box.exec_()
        self.srwr_lu_dia.close()

    def populate_list(self, table_id):
        """
        populate the list view on initialisation and when radio buttons are toggled,
        this view is just for show because QSqlQueryModel class does not handle editing
        but data need to be displayed as concatenated strings, this is not allowed in a
        QSqlTableModel class
        :param table_id: the id passed from the radio button
        :return: void
        """
        self.srwr_lu_dia.ui.typeDescLineEdit.clear()
        self.items_model = QSqlQueryModel()
        self.items_model.setQuery(self.queries[table_id], self.db)
        while self.items_model.canFetchMore():
            self.items_model.fetchMore()
        self.srwr_lu_dia.ui.typeNoSpinBox.setValue(0)
        self.srwr_lu_dia.ui.itemsListView.setModel(self.items_model)
        self.srwr_lu_dia.ui.itemsListView.setModelColumn(1)
        self.create_data_model(table_id)

    def create_data_model(self, table_id):
        """
        create an object from the QSqlTableModel class used to data modifications
        to send to the database
        :param table_id: the id passed from the radio button
        :return: void
        """
        self.data_model = QSqlTableModel(db=self.db)
        self.data_model.setTable(self.tables[table_id])
        self.data_model.setEditStrategy(QSqlTableModel.OnManualSubmit)
        self.data_model.setSort(2, Qt.AscendingOrder)
        self.data_model.select()
        while self.data_model.canFetchMore():
            self.data_model.fetchMore()

    def add_lookup(self):
        """
        get the max value each table model and increment of 1
        add a record to the database when the add button is pressed
        with the incremented value
        :return: void
        """
        ui = self.srwr_lu_dia.ui
        if ui.desRadioButton.isChecked():
            table_id = 0
            table = self.tables[table_id]
            ref_col = self.columns[0]
        elif ui.reinsRadioButton.isChecked():
            table_id = 1
            table = self.tables[table_id]
            ref_col = self.columns[1]
        elif ui.statRadioButton.isChecked():
            table_id = 2
            table = self.tables[table_id]
            ref_col = self.columns[2]

        # format text and numbers
        add_desc = str(ui.typeDescLineEdit.text()).strip()
        add_desc.replace("'", "''")
        add_code = ui.typeNoSpinBox.value()
        if add_desc == "" or add_code is None:
            desc_error_msg_box = QMessageBox(
                QMessageBox.Warning, " ",
                "You must enter the code AND description", QMessageBox.Ok,
                None)
            desc_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                              | Qt.WindowTitleHint)
            desc_error_msg_box.exec_()
            return

        # avoid duplicate insertion on double click on 'Add' button
        sel_model = ui.itemsListView.selectionModel()
        if sel_model.selectedIndexes():
            # extracts just the id from the string
            sel_items = sel_model.selectedIndexes()[0]
            item_data = str(sel_items.data())
            p = re.compile("([0-9]{1,3})(?=\s:)")
            src = p.search(item_data)
            item_id = int(src.group(1))
            if item_id == add_code:
                dups_error_msg_box = QMessageBox(
                    QMessageBox.Warning, " ", "Cannot add duplicate values",
                    QMessageBox.Ok, None)
                dups_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                  | Qt.WindowTitleHint)
                dups_error_msg_box.exec_()
                return

        # Avoid duplicate insertion by checking database
        sql_find_duplicates = """SELECT {0} FROM {1}
                                 WHERE {0} IS '{2}'""".format(
            ref_col, table, add_code)
        if config.DEBUG_MODE:
            print(
                'DEBUG_MODE: find_duplicates: {}'.format(sql_find_duplicates))
        query = QSqlQuery(sql_find_duplicates, self.db)
        if query.first():  # False unless value already found in table
            dup_values_msg_box = QMessageBox(QMessageBox.Warning, " ",
                                             "Cannot add duplicate values",
                                             QMessageBox.Ok, None)
            dup_values_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                              | Qt.WindowTitleHint)
            dup_values_msg_box.exec_()
            return

        # create the record to insert
        data_model_idx = self.data_model.createIndex(
            self.data_model.rowCount() - 1, 0)
        insert_record = self.data_model.record(self.items_model.rowCount())
        insert_record.setValue(1, add_code)
        insert_record.setValue(2, add_desc)
        insert_record.setValue(3, str(""))
        insert_record.setValue(4, str(""))
        self.data_model.insertRecord(self.items_model.rowCount(),
                                     insert_record)
        if self.data_model.submitAll():
            # clear the line input and selects the newly created value on the list
            ui.typeDescLineEdit.clear()
            ui.typeNoSpinBox.setValue(1)
            self.populate_list(table_id)
            index = ui.itemsListView.model().createIndex(
                self.items_model.rowCount() - 1, 1)
            ui.itemsListView.setCurrentIndex(index)
            self.changes_made = True
        else:
            db_error_msg_box = QMessageBox(
                QMessageBox.Warning, " ",
                "Error: {}".format(self.data_model.lastError().text()),
                QMessageBox.Ok, None)
            db_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                            | Qt.WindowTitleHint)
            db_error_msg_box.exec_()
            return

    def selection_handler(self, table_id=None):
        """
        Populate the typeNoSpinBox and typeDescLineEdit with data from the 
        selected row in the list.  The data are extracted from the string
        value itself, without reference to the original model.
        :return void:
        """
        # print all selected list items to the text box
        sel_model = self.srwr_lu_dia.ui.itemsListView.selectionModel()
        sel_items = sel_model.selectedIndexes()[0]
        item_data = str(sel_items.data())
        # split text from the code number
        p = re.compile("\:(.*)")
        src = p.search(item_data)
        item_text = str(src.group(1)[1:])
        p = re.compile("([0-9]{1,3})(?=\s:)")
        src = p.search(item_data)
        item_id = int(src.group(1))
        self.srwr_lu_dia.ui.typeNoSpinBox.setValue(item_id)
        self.srwr_lu_dia.ui.typeDescLineEdit.setText(item_text)

    def remove_lookup(self):
        """
        this function deletes selected items from the list view and db, only if
        the lookups are not used, in this case it prevents the removal displaying
        the list of the streets that use the lookup
        :return: void
        """
        ui = self.srwr_lu_dia.ui
        if ui.desRadioButton.isChecked():
            table_id = 0
            table = self.tables[table_id]
            ref_col = self.columns[0]
            sql_usrns = "SELECT usrn FROM tblSPEC_DES WHERE " \
                         "(designation_code = {0} AND currency_flag=0);" \
                         .format(str(ui.typeNoSpinBox.value()))
        elif ui.reinsRadioButton.isChecked():
            table_id = 1
            table = self.tables[table_id]
            ref_col = self.columns[1]
            sql_usrns = "SELECT usrn FROM tblREINS_CAT WHERE " \
                         "(reinstatement_code = {0} AND currency_flag=0);" \
                         .format(str(ui.typeNoSpinBox.value()))
        elif ui.statRadioButton.isChecked():
            table_id = 2
            table = self.tables[table_id]
            ref_col = self.columns[2]
            sql_usrns = "SELECT usrn FROM tblMaint WHERE " \
                         "(road_status_ref = {0} AND currency_flag=0);" \
                         .format(str(ui.typeNoSpinBox.value()))

        data_model = self.data_model
        item_text = ui.typeDescLineEdit.text()
        item_ref = ui.typeNoSpinBox.value()
        selection_model = ui.itemsListView.selectionModel()
        try:
            item_to_remove = selection_model.selectedIndexes()[0]
        except IndexError:  # Throws if nothing selected
            return

        # prevent deleting the default lookup just for designation and road status
        if table_id == 0 or table_id == 2:
            if item_text == "-none-" or item_ref == 0:
                # not_remove_message = self.srwr_lu_dia.ui.removeButton
                remove_error_msg_box = QMessageBox(
                    QMessageBox.Warning, " ", "This item cannot be removed",
                    QMessageBox.Ok, None)
                remove_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                    | Qt.WindowTitleHint)
                remove_error_msg_box.exec_()
                return

        # Check for USRNs that use this item
        query = QSqlQuery(sql_usrns, self.db)
        usrns = []
        while query.next():
            usrns.append(str(query.value(0)))
        if len(usrns) > 0:
            # Create a message
            message = ("This item cannot be deleted because is used by the "
                       "following streets: \n")
            usrns_string = ', '.join(usrns[:20])
            if len(usrns) > 20:
                usrns_string += ' and more...'
            long_message = message + usrns_string
            # Display warning message in box, then exit
            item_not_deletable_msg_box = QMessageBox(QMessageBox.Warning, " ",
                                                     long_message,
                                                     QMessageBox.Ok, None)
            item_not_deletable_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                      | Qt.WindowTitleHint)
            item_not_deletable_msg_box.exec_()
            return

        # Remove selected row and clear the line edit
        sql_remove_item = """DELETE FROM {}
                             WHERE {} IS {};""".format(table, ref_col,
                                                       item_ref)
        if config.DEBUG_MODE:
            print('DEBUG_MODE: remove_item: {}'.format(sql_remove_item))
        query = QSqlQuery(sql_remove_item, self.db)  # Query is excuted here
        ui.typeDescLineEdit.clear()

        # Check the delete was successful
        if query.numRowsAffected > 0:
            # Repopulate table and select previous item in list
            self.populate_list(table_id)
            if item_to_remove.row() == 0:
                index = ui.itemsListView.model().createIndex(0, 1)
            else:
                index = ui.itemsListView.model().createIndex(
                    item_to_remove.row() - 1, 1)
            ui.itemsListView.setCurrentIndex(index)
            self.selection_handler(table_id)
            self.changes_made = True
        else:
            db_error_msg_box = QMessageBox(
                QMessageBox.Warning, " ",
                "Error: {}".format(data_model.lastError.text(), QMessageBox.Ok,
                                   None))
            db_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                            | Qt.WindowTitleHint)
            db_error_msg_box.exec_()
        return

    def amend_lookup(self):
        """
        change the value of existing lookup items, this time are used db queries
        :return: void
        """
        table_id = None
        if self.srwr_lu_dia.ui.typeDescLineEdit.text() == "":
            return
        item_id = self.srwr_lu_dia.ui.typeNoSpinBox.value()
        selection_model = self.srwr_lu_dia.ui.itemsListView.selectionModel()
        selection_indexes = selection_model.selectedIndexes()
        # if nothing is selects exit the function
        if not selection_indexes:
            return
        selection_index = selection_indexes[0]
        if selection_index.data() == "0 : -none-":
            # if the selected value is -none- fire an alert
            not_edit_msg_box = QMessageBox(QMessageBox.Warning, " ",
                                           "This item cannot be edited",
                                           QMessageBox.Ok, None)
            not_edit_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                            | Qt.WindowTitleHint)
            not_edit_msg_box.exec_()
            return
        # changes the values directly onto the db
        des_radio_btn = self.srwr_lu_dia.ui.desRadioButton
        reins_radio_btn = self.srwr_lu_dia.ui.reinsRadioButton
        stat_radio_btn = self.srwr_lu_dia.ui.statRadioButton
        amend_query = QSqlQuery(self.db)
        if des_radio_btn.isChecked():
            table_id = 0
            format_query = self.amend_queries[0].format(
                self.srwr_lu_dia.ui.typeDescLineEdit.text(), item_id)
            if not amend_query.exec_(format_query):
                db_error_msg_box = QMessageBox(
                    QMessageBox.Warning, " ",
                    "Error: {}".format(amend_query.lastError().text()),
                    QMessageBox.Ok, None)
                db_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                | Qt.WindowTitleHint)
                db_error_msg_box.exec_()
        if reins_radio_btn.isChecked():
            table_id = 1
            format_query = self.amend_queries[1].format(
                self.srwr_lu_dia.ui.typeDescLineEdit.text(), item_id)
            if not amend_query.exec_(format_query):
                db_error_msg_box = QMessageBox(
                    QMessageBox.Warning, " ",
                    "Error: {}".format(amend_query.lastError().text()),
                    QMessageBox.Ok, None)
                db_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                | Qt.WindowTitleHint)
                db_error_msg_box.exec_()
        if stat_radio_btn.isChecked():
            table_id = 2
            format_query = self.amend_queries[2].format(
                self.srwr_lu_dia.ui.typeDescLineEdit.text(), item_id)
            if not amend_query.exec_(format_query):
                db_error_msg_box = QMessageBox(
                    QMessageBox.Warning, " ",
                    "Error: {}".format(amend_query.lastError().text()),
                    QMessageBox.Ok, None)
                db_error_msg_box.setWindowFlags(Qt.CustomizeWindowHint
                                                | Qt.WindowTitleHint)
                db_error_msg_box.exec_()
        # closes the query and repopulate the list
        self.changes_made = True
        amend_query.clear()
        self.populate_list(table_id)
Ejemplo n.º 21
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.º 22
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.º 23
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.º 24
0
class dlgSelectCuenta( QDialog ):

    def __init__( self, parent = None ):
        super( dlgSelectCuenta, self ).__init__( parent )
        self.padre = parent

        self.ctaBancomodel = QSqlQueryModel()
        self.ctaBancomodel.setQuery( """
        SELECT
            b.descripcion as Banco,
            cb.ctabancaria as 'No. Cuenta',
            tm.simbolo as Moneda,
            c.codigo as 'Codigo Contable',
            c.idcuenta as Id,
            c.descripcion as 'Cuenta Contable',
            IF(
                con.fecha IS NULL,
                LAST_DAY(MIN(d.fechacreacion)),
                (MAX(con.fecha) + INTERVAL 1 MONTH))
                AS conciliar

        FROM cuentasbancarias cb
        JOIN bancos b ON cb.idbanco=b.idbanco
        JOIN cuentascontables c ON c.idcuenta=cb.idcuentacontable
        JOIN tiposmoneda tm ON tm.idtipomoneda=cb.idtipomoneda
        LEFT JOIN conciliaciones con ON con.idcuentabancaria=cb.idcuentacontable
        LEFT JOIN cuentasxdocumento cd ON cd.idcuenta=c.idcuenta
        LEFT JOIN documentos d ON cd.iddocumento = d.iddocumento
        WHERE d.iddocumento IS NOT NULL
        GROUP BY c.idcuenta
         ;
        """ )
#        
#        if self.ctaBancomodel.rowCount() == 0 :
#            QMessageBox.critical(self,"Cuentas Bancarias","No existe ninguna cuenta bancaria")
#            self.destroy()


        self.setWindowTitle( u"Elija fecha y cuenta bancaria para la conciliación" )
        self.filtermodel = QSortFilterProxyModel()
        self.filtermodel.setSourceModel( self.ctaBancomodel )
        self.filtermodel.setFilterCaseSensitivity( Qt.CaseInsensitive )
        self.filtermodel.setFilterKeyColumn( -1 )

        self.tblCuenta = QTableView()
        self.tblCuenta.setSelectionMode( QAbstractItemView.SingleSelection )
        self.tblCuenta.setSelectionBehavior( QAbstractItemView.SelectRows )

        self.tblCuenta.setModel( self.filtermodel )
        buttonbox = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel )

        self.txtSearch = QLineEdit()
        formlayout = QFormLayout()

        formlayout.addRow( "&Buscar", self.txtSearch )



        self.dtPicker = QDateTimeEdit()
        self.dtPicker.setReadOnly( True )
#        self.dtPicker.setCalendarPopup(True)                                       
        self.dtPicker.setAlignment( Qt.AlignHCenter )
        self.dtPicker.setDisplayFormat( "MMMM 'd'el yyyy" )
#        self.dtPicker.setMinimumDate(QDate(2009,1,1))
        fecha = QDate.currentDate()
        self.dtPicker.setDate( QDate( fecha.year(), fecha.month(), fecha.daysInMonth() ) )

        fechalayout = QFormLayout()
        fechalayout.addRow( "&Fecha", self.dtPicker )

        layout = QVBoxLayout()


        layout.addLayout( fechalayout )
        layout.addWidget( self.tblCuenta )
        layout.addLayout( formlayout )
        layout.addWidget( buttonbox )
        self.setLayout( layout )

        self.setMinimumWidth( 400 )

        buttonbox.accepted.connect( self.aceptar )
        buttonbox.rejected.connect( self.reject )
        self.txtSearch.textChanged[unicode].connect( self.updateFilter )
        self.tblCuenta.selectionModel().currentChanged[QModelIndex, QModelIndex].connect( self.on_tblCuenta_currentChanged )

        self.setModal( True )
        self.setWindowFlags( Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint | Qt.WindowTitleHint )
        self.show()
        self.tblCuenta.setFocus()
        self.tblCuenta.selectRow( 0 )
        self.tblCuenta.setColumnHidden( 4, True )
        self.tblCuenta.setColumnHidden( 5, True )
        self.tblCuenta.setColumnHidden( 6, True )
        self.tblCuenta.horizontalHeader().setStretchLastSection( True )
        self.tblCuenta.resizeColumnsToContents()

    @property
    def data( self ):
        data = {}
        fila = self.tblCuenta.selectionModel().currentIndex().row()
        fecha = self.dtPicker.date()

        data['banco'] = self.filtermodel.index( fila, 0 ).data().toString()
        data['id_cuenta_contable'] = self.filtermodel.index( fila, 4 ).data().toInt()[0]
        data['codigo_cuenta_contable'] = self.filtermodel.index( fila, 3 ).data().toString()
        data['cuenta_bancaria'] = self.filtermodel.index( fila, 5 ).data().toString()
        data['fecha'] = QDate( fecha.year(), fecha.month(), fecha.daysInMonth() )
        data['moneda'] = self.filtermodel.index( fila, 2 ).data().toString()


        if not QSqlDatabase.database().isOpen() and not QSqlDatabase.open():
            raise Exception( QSqlDatabase.lastError() )

        query = QSqlQuery()
        if not query.exec_( "CALL spSaldoCuenta( %d, %s )" % ( 
                data['id_cuenta_contable'],
                QDate( data['fecha'].year(), data['fecha'].month(), data['fecha'].daysInMonth() ).toString( "yyyyMMdd" )
            )
        ):
            raise Exception( query.lastError().text() )

        query.first()

        data['saldo_inicial_libro'] = Decimal( query.value( 0 ).toString() )



        return data

    def aceptar( self ):
        fecha = QDate.currentDate()
        fecha = QDate( fecha.year(), fecha.month(), fecha.daysInMonth() )
        if self.dtPicker.date() > fecha:
            QMessageBox.information( None, "Cuentas Bancarias", "La cuenta seleccionada ya fue conciliada" )
        else:
            return self.accept()


    def exec_( self ):
        if self.ctaBancomodel.rowCount() == 0:
            QMessageBox.critical( self.padre, "Cuentas Bancarias",
                "No existe ninguna cuenta bancaria con movimientos en este mes" )
            return self.reject()
        else:
            return QDialog.exec_( self )

    def updateFilter( self, str ):
        self.filtermodel.setFilterWildcard( str )

#    @pyqtSlot( "QModelIndex" )
#    def on_tblCuenta_clicked(self, index):
    def on_tblCuenta_currentChanged( self, _current, _previous ):
        fila = self.tblCuenta.selectionModel().currentIndex().row()
        fecha = self.filtermodel.index( fila, 6 ).data().toDate()
        if fecha.toString() != "":
            self.dtPicker.setDate( fecha )
        else:
            fecha = QDate.currentDate()
Ejemplo n.º 25
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.º 26
0
class FrmMovimientosBancarios(Ui_frmMovimientosBancarios, Base):
    def __init__(self, parent):
        super(FrmMovimientosBancarios, self).__init__(parent)

        self._iniciarClase(parent)
        self._iniciarInterfaz()

        # Carga los modelos de forma paralela a la ejecucion del sistema
        QTimer.singleShot(0, self.loadModels)

    def _iniciarClase(self, parent):
        """
        Ejecuta constructores de las clases e inicializa variables
        """

        self.parentWindow = parent

        self.navmodel = None
        """
        @ivar: Modelo de navegacion que se asignara a la tabla 
        principal de navegacion
        @type: QSqlQueryModel
        """

        self.navproxymodel = None
        """
        @ivar: = Proxy del modelo de navegacion que filtra al momento 
        de una busqueda
        @type: QSortFilterProxyModel  
        """

        self.detailsmodel = None
        """
        @ivar: Modelo detalle, carga las lineas del documento
        @type: QSqlQueryModel
        """

        # Proxy para el modelo detalle, que filtra al navegar para solo mostrar las lineas relacionadas al documento actual
        self.detailsproxymodel = QSortFilterProxyModel(self)
        self.detailsproxymodel.setSourceModel(self.detailsmodel)

        # Modelo de Edicion
        self.editmodel = None

    def _iniciarInterfaz(self):
        """
        Realiza Cambios iniciales al formulario
        """
        self.cbcuenta = SearchPanel(None, None, True)
        self.cbcuenta.lineEdit().setAlignment(Qt.AlignHCenter)
        self.cbcuenta.currentIndexChanged[int].connect(self.on_cbcuenta_currentIndexChanged)
        """
        @ivar: El combo con en el que se cargan las cuentas
        @type: SearcPanel
        """
        self.horizontalLayout_32.addWidget(self.cbcuenta)
        self.actionSave.setVisible(False)
        self.actionCancel.setVisible(False)
        self.cbconcepto.view().setMinimumHeight(60)
        self.dtPicker.setDateTime(QDateTime.currentDateTime())

    @pyqtSlot(QDateTime)
    @if_edit_model
    def on_dtPicker_dateTimeChanged(self, datetime):
        self.editmodel.fechaDoc = datetime

    @pyqtSlot(int)
    @if_edit_model
    def on_cbcuenta_currentIndexChanged(self, index):
        self.editmodel.setData(
            self.editmodel.index(0, 2),
            [
                self.cuentasModel.record(index).value("idcuentacontable").toInt()[0],
                self.cuentasModel.record(index).value("codigo").toString(),
                self.cuentasModel.record(index).value("Cuenta Contable").toString(),
            ],
        )

    #        self.accountseditdelegate.accounts.setFilterRegExp( "[^%d]" % self.cuentabancaria.record( index ).value( "idcuentacontable" ).toInt()[0] )

    def updateDetailFilter(self, _index):
        self.detailsproxymodel.setFilterKeyColumn(IDDOCUMENTO)
        iddoc = self.navmodel.record(_index).value("iddocumento").toString()
        self.detailsproxymodel.setFilterRegExp(iddoc)

    def save(self):
        self.editmodel.observacionesDoc = self.txtobservaciones.toPlainText()
        self.editmodel.lineasDoc = self.editmodel.lines
        self.editmodel.totalDoc = self.editmodel.lineasDoc[0].amount
        if self.editmodel.valid:
            Base.save(self, True)
        else:
            QMessageBox.information(None, "Datos Incompletos", self.editmodel.mensajeError)

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

    @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]

    def newDocument(self):
        """
        activar todos los controles, llena los modelos necesarios, 
        crear el modelo de edidicion
        """
        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 = MovimientosBancariosModel()
            self.editmodel.tipoDoc = constantes.IDDEPOSITO

            self.cuentasModel = QSqlQueryModel()
            self.cuentasModel.setQuery(
                """
            SELECT
                c.idcuentacontable,
                cc.codigo,
                cc.descripcion as 'Cuenta Contable',
                CONCAT(c.ctabancaria, ' [ ' , b.descripcion, ' - ', tm.simbolo, ' ]') as 'Cuenta Bancaria'
            FROM cuentasbancarias c
            JOIN bancos b ON b.idbanco = c.idbanco
            JOIN tiposmoneda tm ON tm.idtipomoneda= c.idtipomoneda
            JOIN cuentascontables cc ON cc.idcuenta = c.idcuentacontable
            ;
            """
            )
            if self.cuentasModel.rowCount() == 0:
                raise UserWarning("No existen cuentas bancarias en la base de datos," + " por favor cree una")

            self.cbcuenta.setModelColumn(3)
            self.cbcuenta.setModel(self.cuentasModel)
            self.cbcuenta.setCurrentIndex(-1)
            self.cbcuenta.tabla.setColumnHidden(0, True)
            # self.cbcuenta.tabla.setColumnHidden(1,True)
            # self.cbcuenta.tabla.setColumnHidden(2,True)

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

            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.cbconcepto.setModel(self.conceptosModel)

            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.insertRow(1)
            self.editmodel.insertRow(1)
            self.editmodel.fechaDoc = QDateTime.currentDateTime()
            self.editmodel.autorId = self.user.uid
            #        Crea un edit delegate para las cuentas
            self.tabledetails.setItemDelegate(self.cuentasDelegate)
            self.tabledetails.setModel(self.editmodel)

            self.tabledetails.setModel(self.editmodel)
            self.txttipodoc.setText("Deposito")
            self.status = False

        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()

    def setControls(self, status):
        """
        Cambia el formulario entre modos de edicion y navegacion
        @param status: false = editando        true = navegando
        """
        self.actionPrint.setVisible(status)
        self.dtPicker.setReadOnly(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)

        if status:
            self.swcuenta.setCurrentIndex(1)
            self.swconcepto.setCurrentIndex(1)
            self.swtipodoc.setCurrentIndex(1)
            self.tabledetails.setEditTriggers(QAbstractItemView.NoEditTriggers)
        else:
            self.tabWidget.setCurrentIndex(0)
            self.txtobservaciones.setPlainText("")
            self.swcuenta.setCurrentIndex(0)
            self.swconcepto.setCurrentIndex(0)
            #            self.swtipodoc.setCurrentIndex( 0 )
            self.tabledetails.setEditTriggers(
                QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked
            )

    def updateModels(self):
        """
        Recargar todos los modelos
        """
        try:
            if not self.database.isOpen():
                self.database.open()

            self.navmodel = QSqlQueryModel()
            self.navmodel.setQuery(
                """
            SELECT
                    d.iddocumento,
                    d.fechacreacion as Fecha,
                    CONCAT(cb.banco, ' ',cb.moneda,' [ ', cb.ncuenta,' ]') AS 'Cuenta Bancaria',
                    td.descripcion as 'Tipo Doc',
                    con.descripcion as Concepto,
                    d.Observacion,
                    cb.ncuenta
            FROM documentos d
            JOIN tiposdoc td ON td.idtipodoc=d.idtipodoc
            JOIN cuentasxdocumento cd ON cd.iddocumento = d.iddocumento
            JOIN vw_cuentasbancarias cb ON cb.idcuenta=cd.idcuenta
            LEFT JOIN conceptos con ON con.idconcepto = d.idconcepto
            WHERE d.idtipodoc=%d
            ORDER BY d.iddocumento,d.fechacreacion DESC
                ; """
                % constantes.IDDEPOSITO
            )

            #        El modelo que filtra a self.navmodel
            self.navproxymodel = QSortFilterProxyModel()
            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.detailsmodel.setQuery(
                """
            SELECT
                c.iddocumento,
                codigo AS 'Codigo',
                cc.descripcion AS 'Descripcion',
                 monto as 'Monto C$'
            FROM cuentasxdocumento c
            JOIN cuentascontables cc ON cc.idcuenta=c.idcuenta
            JOIN documentos d ON d.iddocumento = c.iddocumento
            JOIN tiposdoc td ON td.idtipodoc = d.idtipodoc AND td.modulo =3
            ORDER BY c.iddocumento,nlinea
            ;"""
            )

            #        Este es el filtro del modelo anterior
            self.detailsproxymodel = QSortFilterProxyModel()
            self.detailsproxymodel.setSourceModel(self.detailsmodel)
            self.detailsproxymodel.setFilterKeyColumn(IDDOCUMENTO)
            self.detailsproxymodel.setFilterRegExp("-1")

            self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
            self.mapper.setModel(self.navproxymodel)
            self.mapper.addMapping(self.txtobservaciones, OBSERVACION)
            self.mapper.addMapping(self.txtconcepto, CONCEPTO)
            self.mapper.addMapping(self.txtcuenta, CUENTA)
            self.mapper.addMapping(self.txttipodoc, TIPODOC)
            self.mapper.addMapping(self.dtPicker, FECHA)

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

            self.tabledetails.setColumnHidden(IDDOCUMENTO, True)
            self.tablenavigation.setColumnHidden(IDDOCUMENTO, True)
            self.tablenavigation.setColumnHidden(NCUENTA, True)
            self.tablenavigation.resizeColumnsToContents()
        #            self.navigate( 'last' )
        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 cargar " + "los datos")
        finally:
            if self.database.isOpen():
                self.database.close