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()
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
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()
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()
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()
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()
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]
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)
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", )
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()
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
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()
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")
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()
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
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()
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 ) )
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)
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)
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]
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()
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()
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
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