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 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()
class FrmKardexOther( Ui_FrmKardexOther, Base ): ''' classdocs ''' def __init__( self, parent = None ): ''' Constructor ''' super( FrmKardexOther, self ).__init__( parent ) self.actionNew.setEnabled( False ) self.navmodel = QSqlQueryModel() self.detailsModel = QSqlQueryModel() self.navproxymodel = QSortFilterProxyModel() self.navproxymodel.setSourceModel( self.navmodel ) self.detailsproxymodel = QSortFilterProxyModel() self.detailsproxymodel.setSourceModel( self.detailsModel ) self.accountsnavmodel = QSqlQueryModel() self.accountsproxymodel = QSortFilterProxyModel() self.accountsproxymodel.setSourceModel( self.accountsnavmodel ) self.editmodel = None if not self.user.hasRole( "contabilidad" ): self.tableaccounts.setVisible( False ) self.lblaccounts.setVisible( False ) QTimer.singleShot( 0, self.loadModels ) def setControls( self, status ): if self.user.hasRole( "contabilidad" ): self.actionNew.setEnabled( True ) self.dtPicker.setReadOnly( False ) self.actionPrint.setVisible( status ) self.actionGoFirst.setVisible( status ) self.actionGoPrevious.setVisible( status ) self.actionGoNext.setVisible( status ) self.actionGoLast.setVisible( status ) self.actionNew.setVisible( status ) self.actionPreview.setVisible( status ) self.actionCancel.setVisible( not status ) self.actionSave.setVisible( not status ) self.swConcept.setCurrentIndex( 0 if status else 1 ) self.swWarehouse.setCurrentIndex( 0 if status else 1 ) self.tabnavigation.setEnabled( status ) self.txtObservations.setReadOnly( status ) self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers if status else QAbstractItemView.AllEditTriggers ) if not status: self.tabWidget.setCurrentIndex( 0 ) self.tabledetails.addAction( self.actionDeleteRow ) else: self.tabledetails.removeAction( self.actionDeleteRow ) self.tabledetails.setModel( self.detailsproxymodel ) self.tablenavigation.setModel( self.navproxymodel ) self.tableaccounts.setModel( self.accountsproxymodel ) self.tabledetails.setColumnHidden( IDARTICULO, True ) self.tabledetails.setColumnHidden( IDDOCUMENTOD, True ) self.tableaccounts.setColumnHidden( IDDOCUMENTOC, True ) self.tableaccounts.setColumnHidden( IDCUENTA, True ) self.tabledetails.setColumnWidth( DESCRIPCION, 300 ) self.tablenavigation.setColumnHidden( IDDOCUMENTO, True ) self.tablenavigation.setColumnHidden( ESTADO, True ) self.tablenavigation.setColumnHidden( OBSERVACIONES, True ) def addActionsToToolBar( self ): if self.user.hasRole( "contabilidad" ): self.toolBar.addActions( [ self.actionNew, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel ] ) else: self.toolBar.addActions( [ self.actionPreview, self.actionPrint, ] ) self.toolBar.addSeparator() self.toolBar.addActions( [ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ] ) if self.user.hasRole( "kardex" ): #si el usuario no es de kardex no deberia de poder dar entrada a bodega self.actionGiveEntry = self.createAction( text = "Dar entrada al documento", icon = QIcon.fromTheme( 'dialog-ok-apply', QIcon( ":/icons/res/dialog-ok-apply.png" ) ), slot = self.giveEntry ) self.toolBar.addActions( [ self.actionGiveEntry ] ) def giveEntry( self ): """ Dar entrada a un kardex """ if QMessageBox.question( self, qApp.organizationName(), u"¿Realmente desea dar entrada a este documento?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: iddoc = self.navmodel.record( self.mapper.currentIndex() ).value( IDDOCUMENTO ).toInt()[0] query = QSqlQuery() try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la"\ + " base de datos" ) if not self.database.transaction(): raise Exception( u"No se pudo iniciar la transacción "\ + "para confirmar el kardex" ) q = """ UPDATE documentos d SET idestado = %d WHERE d.iddocumento = %d LIMIT 1 """ % ( constantes.CONFIRMADO, iddoc ) if not query.exec_( q ): raise Exception( u"No se pudo actualizar el estado "\ + "del documento" ) if not query.exec_( """ INSERT INTO documentos (ndocimpreso, fechacreacion, idtipodoc, total, idtipocambio, idbodega) SELECT fnConsecutivo(%d,NULL), NOW(), %d, total, idtipocambio, idbodega FROM documentos WHERE iddocumento = %d; """ % ( constantes.IDKARDEX, constantes.IDKARDEX, iddoc ) ): raise Exception( u"No se pudo insertar el documento kardex" ) insertedId = query.lastInsertId().toInt()[0] if not query.exec_( """ INSERT INTO docpadrehijos (idpadre, idhijo) VALUES (%d, %d) """ % ( iddoc, insertedId ) ): raise Exception( u"No se pudo crear la relación entre el"\ + " documento ajuste de bodega y su kardex" ) if not self.database.commit(): raise Exception( u"No se pudo hacer commit" ) QMessageBox.information( self, qApp.organizationName(), "El documento se ha guardado con exito" ) self.updateModels() except UserWarning as inst: logging.error( unicode( inst ) ) self.database.rollback() QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) self.database.rollback() QMessageBox.critical( self, qApp.organizationName(), u"No se pudo confirmar la entrada"\ + " de este documento" ) def deleteRow( self ): """ Funcion usada para borrar lineas de la tabla """ index = self.tabledetails.currentIndex() if not index.isValid(): return row = index.row() self.editmodel.removeRows( row, 1 ) def updateModels( self ): try: if not QSqlDatabase.database().isOpen(): if not QSqlDatabase.database().open: raise UserWarning( "No se pudo conectar con la base datos" ) query = """ SELECT d.iddocumento, d.ndocimpreso AS 'Ndoc', d.fechacreacion, d.observacion, b.nombrebodega AS 'Bodega', d.total AS 'Total', d.idestado, c.descripcion AS 'Concepto', IF( dph.idhijo IS NULL, 1, 0) AS 'Pendiente' FROM documentos d JOIN bodegas b ON b.idbodega = d.idbodega JOIN conceptos c ON c.idconcepto = d.idconcepto LEFT JOIN docpadrehijos dph ON dph.idpadre = d.iddocumento LEFT JOIN documentos kardex ON dph.idhijo = kardex.iddocumento AND kardex.idtipodoc = %d WHERE d.idtipodoc = %d """ % ( constantes.IDKARDEX, constantes.IDAJUSTEBODEGA ) self.navmodel.setQuery( query ) query = """ SELECT a.idarticulo, a.descripcion, axd.costounit, axd.unidades, axd.iddocumento FROM vw_articulosdescritos a JOIN articulosxdocumento axd ON axd.idarticulo = a.idarticulo JOIN documentos d ON d.iddocumento = axd.iddocumento AND d.idtipodoc = %d LEFT JOIN docpadrehijos dph ON dph.idhijo = d.iddocumento WHERE dph.idhijo IS NULL """ % constantes.IDAJUSTEBODEGA self.detailsModel.setQuery( query ) if self.user.hasAnyRole( ["inventario", "contabilidad"] ): query = """ SELECT cc.idcuenta, cc.codigo, cc.descripcion, cxd.monto, cxd.iddocumento FROM cuentasxdocumento cxd JOIN documentos d ON d.iddocumento = cxd.iddocumento AND d.idtipodoc = %d JOIN cuentascontables cc ON cxd.idcuenta = cc.idcuenta """ % constantes.IDAJUSTEBODEGA self.accountsnavmodel.setQuery( query ) self.mapper.setModel( self.navproxymodel ) self.mapper.addMapping( self.txtPrintedDocumentNumber, NDOCIMPRESO ) self.mapper.addMapping( self.txtConcept, CONCEPT ) self.mapper.addMapping( self.txtWarehouse, BODEGA ) self.mapper.addMapping( self.txtObservations, OBSERVACIONES ) self.mapper.addMapping( self.dtPicker, FECHA ) except UserWarning as inst: QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) logging.error( unicode( inst ) ) except Exception as inst: QMessageBox.critical( self, qApp.organizationName(), u"No se pudo iniciar un nuevo ajuste de kardex" ) logging.critical( unicode( inst ) ) def updateDetailFilter( self, index ): curr_id = self.navmodel.record( index ).value( IDDOCUMENTO ).toInt()[0] self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOD ) self.detailsproxymodel.setFilterRegExp( "^%d$" % curr_id ) self.accountsproxymodel.setFilterKeyColumn( IDDOCUMENTOC ) self.accountsproxymodel.setFilterRegExp( "^%d$" % curr_id ) if self.user.hasRole( 'kardex' ): estado = self.navmodel.record( index ).value( PENDIENTE ).toInt()[0] self.actionGiveEntry.setVisible( estado == 1 ) def newDocument( self ): try: if not QSqlDatabase.database().isOpen(): if not QSqlDatabase.database().open: raise UserWarning( "No se pudo conectar con la "\ + "base de datos" ) self.editmodel = KardexOtherModel() self.editmodel.uid = self.user.uid conceptosmodel = QSqlQueryModel() conceptosmodel.setQuery( """ SELECT c.idconcepto, c.descripcion FROM conceptos c WHERE c.idtipodoc = %d """ % constantes.IDAJUSTEBODEGA ) if conceptosmodel.rowCount() == 0: raise UserWarning( u"No existen conceptos para los "\ + "ajustes de bodega" ) self.cbConcept.setModel( conceptosmodel ) self.cbConcept.setModelColumn( 1 ) warehouseModel = QSqlQueryModel() warehouseModel.setQuery( """ SELECT idbodega, nombrebodega FROM bodegas b ORDER BY idbodega """ ) self.cbWarehouse.setModel( warehouseModel ) self.cbWarehouse.setModelColumn( 1 ) #Calcular el numero de kardex query = QSqlQuery( """ CALL spConsecutivo(%d,NULL); """ % constantes.IDAJUSTEBODEGA ) if not query.exec_(): raise UserWarning( "No se pudo calcular el numero "\ + "del kardex" ) query.first() self.editmodel.printedDocumentNumber = query.value( 0 ).toString() self.txtPrintedDocumentNumber.setText( self.editmodel.printedDocumentNumber ) articlesmodel = QSqlQueryModel() articlesmodel.setQuery( """ SELECT a.idarticulo, a.descripcion, ca.valor as costo FROM vw_articulosdescritos a JOIN costosarticulo ca ON a.idarticulo = ca.idarticulo AND ca.activo = 1 """ ) delegate = KardexOtherDelegate( articlesmodel ) self.tabledetails.setItemDelegate( delegate ) self.tabledetails.setModel( self.editmodel ) accountsdelegate = AccountsSelectorDelegate( QSqlQuery( """ SELECT c.idcuenta, c.codigo, c.descripcion FROM cuentascontables c JOIN cuentascontables p ON c.padre = p.idcuenta AND p.padre != 1 WHERE c.padre != 1 AND c.idcuenta != 22 """ ), True ) self.tableaccounts.setItemDelegate( accountsdelegate ) self.tableaccounts.setModel( self.editmodel.accountsmodel ) self.editmodel.accountsmodel.insertRows( 0, 2 ) line = AccountsSelectorLine() line.itemId = int( movimientos.INVENTARIO ) line.code = "110 003 001 000 000" line.name = "INV Inventario de Bodega" self.editmodel.accountsmodel.lines[0] = line self.addLine() self.dtPicker.setDateTime( QDateTime.currentDateTime() ) self.status = False except UserWarning as inst: QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) self.status = True except Exception as inst: QMessageBox.critical( self, qApp.organizationName(), "El sistema no pudo iniciar una nueva entrada de kardex" ) self.status = True def cancel( self ): u""" Borrar todos los modelos que se hallan creado para el modo edición, asignar los modelos de navegación a las vistas """ self.editmodel = None self.tabledetails.setModel( self.detailsproxymodel ) self.status = True @pyqtSlot( int ) @if_edit_model def on_cbWarehouse_currentIndexChanged( self, index ): self.editmodel.warehouseId = self.cbWarehouse.model().index( index, 0 ).data().toInt()[0] @pyqtSlot( int ) @if_edit_model def on_cbConcept_currentIndexChanged( self, index ): self.editmodel.conceptId = self.cbConcept.model().index( index, 0 ).data().toInt()[0]
class FrmPersona( Ui_frmPersona, Base ): def __init__( self, tipo, rol, parent ): super( FrmPersona, self ).__init__( parent, True ) self.tabledetails = None self.setWindowModality( Qt.WindowModal ) self.setWindowFlags( Qt.Dialog ) self.tipo = tipo self.rol = rol self.lbltitulo.setText( u"<B>Datos del %s</B>" % rol ) self.editmodel = None # self.parent = parent self.navmodel = QSqlQueryModel() self.navproxymodel = QSortFilterProxyModel() self.navproxymodel.setFilterKeyColumn( -1 ) self.navproxymodel.setSourceModel( self.navmodel ) self.navproxymodel.setFilterCaseSensitivity( Qt.CaseInsensitive ) self.tablenavigation.setModel( self.navproxymodel ) self.actionPreview.setVisible( False ) self.actionPrint.setVisible( False ) self.updateModels() self.status = True def updateDetailFilter( self, index ): self.actionEditar.setEnabled( self.navproxymodel.rowCount() > 0 ) if self.navmodel.record( index ).value( "activo" ).toBool(): self.rbactivo.setChecked( True ) else: self.rbinactivo.setChecked( True ) def updateModels( self ): try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( "No se pudo abrir la base de datos" ) #TODO: Esta consulta tiene que mejorar para definir realmente quien es el que realiza el arqueo query = u""" SELECT tipopersona, idpersona, Nombre, direccion as 'Dirección', telefono as 'Teléfono', email as 'E-mail', ruc as Ruc, activo FROM personas p WHERE tipopersona =%d """ % self.tipo self.navmodel.setQuery( query ) self.navproxymodel.setSourceModel( self.navmodel ) self.actionEditar.setEnabled( self.navproxymodel.rowCount() > 0 ) self.tablenavigation.setModel( self.navproxymodel ) self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit ) self.mapper.setModel( self.navproxymodel ) self.mapper.addMapping( self.txtnombre, NOMBRE ) self.mapper.addMapping( self.txtdireccion, DIRECCION ) self.mapper.addMapping( self.txttelefono, TELEFONO ) self.mapper.addMapping( self.txtcorreo, CORREO ) self.mapper.addMapping( self.txtruc, RUC ) self.tablenavigation.setColumnHidden( TIPO, True ) self.tablenavigation.setColumnHidden( ID, True ) self.tablenavigation.setColumnHidden( ACTIVO, True ) self.tablenavigation.setColumnWidth( NOMBRE, 200 ) self.navigate( 'last' ) # self.mapper.setCurrentIndex( index.row() ) except UserWarning as inst: logging.error( inst ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( inst ) finally: if self.database.isOpen(): self.database.close() def save( self ): editado = self.status == 2 titulo = "Guardar los cambios" if editado else "Crear un nuevo %s" % self.rol if self.txtnombre.text() == "": self.txtnombre.setFocus() QMessageBox.warning( None, titulo, "Por favor escriba el nombre del %s" % self.rol ) return False if QMessageBox.question( None, titulo, u"¿Está seguro que desea guardar los cambios?" if editado else u"¿Está seguro que desea crear al %s?" % self.rol , QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No: return False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos" ) query = QSqlQuery() pos = self.mapper.currentIndex() if editado: query.prepare( """ UPDATE personas SET direccion =:dir, telefono=:tel, email=:correo, ruc=:ruc, tipopersona = :tipo, activo=:activo WHERE idpersona = :idpersona LIMIT 1; """ ) query.bindValue( ":idpersona", self.navmodel.record( self.mapper.currentIndex() ).value( "idpersona" ).toInt()[0] ) else: query.prepare( """ INSERT INTO personas(nombre,fechaingreso,direccion,telefono,email,ruc,tipopersona,activo) VALUES (:nombre,NOW(),:dir,:tel,:correo,:ruc,:tipo,:activo) """ ) query.bindValue( ":nombre", self.txtnombre.text() ) query.bindValue( ":dir", self.txtdireccion.text() ) query.bindValue( ":tel", self.txttelefono.text() ) query.bindValue( ":correo", self.txtcorreo.text() ) query.bindValue( ":ruc", self.txtruc.text() ) query.bindValue( ":tipo", self.tipo ) query.bindValue( ":activo", 1 if self.rbactivo.isChecked() else 0 ) if not query.exec_(): raise Exception( query.lastError().text() ) QMessageBox.information( None, titulo, "Los cambios fueron guardados" if editado else "El %s fue creado exitosamente" % self.rol ) self.updateModels() self.status = True result = True if editado: self.mapper.setCurrentIndex( pos ) except UserWarning as inst: logging.error( unicode( inst ) ) logging.error( query.lastError().text() ) QMessageBox.critical( self, titulo, unicode( inst ) ) result = False except Exception as inst: logging.critical( unicode( inst ) ) logging.critical( query.lastError().text() ) QMessageBox.critical( self, titulo, "El %s no pudo ser creado" % self.rol ) result = False finally: if self.database.isOpen(): self.database.close() return result def cancel( self ): self.editmodel = None self.status = True self.navigate( 'last' ) def addActionsToToolBar( self ): self.actionEditar = self.createAction( text = "Editar", tip = u"Editar la persona", icon = QIcon.fromTheme( 'document-edit', QIcon( ":/icons/res/document-edit.png" ) ), slot = functools.partial( self._setStatus, 2 ) ) self.toolBar.addActions( [ self.actionEditar ] ) super( FrmPersona, self ).addActionsToToolBar() def setControls( self, status ): if status == 2 and self.navproxymodel.rowCount() == 0: return if status == False: self.txtnombre.setText( "" ) self.txtnombre.setFocus() self.txtdireccion.setText( "" ) self.txtcorreo.setText( "" ) self.txtruc.setText( "" ) self.txttelefono.setText( "" ) self.rbactivo.setChecked( True ) self.txtnombre.setReadOnly( False ) elif status == True: self.tablenavigation.setFocus() self.txtnombre.setReadOnly( True ) else: self.txtdireccion.setFocus() status = False self.tabWidget.setCurrentIndex( 0 if status == False else 1 ) self.rbactivo.setEnabled( not status ) self.rbinactivo.setEnabled( not status ) self.tablenavigation.setEnabled( status ) self.tabnavigation.setEnabled( status ) self.actionNew.setVisible( status ) self.actionCancel.setVisible( not status ) self.actionSave.setVisible( not status ) self.actionEditar.setVisible( status ) self.actionGoFirst.setVisible( status ) self.actionGoLast.setVisible( status ) self.actionGoNext.setVisible( status ) self.actionGoPrevious.setVisible( status ) self.txtcorreo.setReadOnly( status ) self.txtdireccion.setReadOnly( status ) self.txtruc.setReadOnly( status ) self.txttelefono.setReadOnly( status ) def newDocument( self ): self.status = False @pyqtSlot( int ) def on_cbnombre_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ index = self.combomodel.mapToSource( self.combomodel.index( index, 0 ) ) index = index.row() self.personaId = self.personasModel.record( index ).value( "idpersona" ).toInt()[0] self.txtcorreo.setText( self.personasModel.record( index ).value( "email" ).toString() ) self.txtdireccion.setText( self.personasModel.record( index ).value( "direccion" ).toString() ) self.txtruc.setText( self.personasModel.record( index ).value( "ruc" ).toString() ) self.txttelefono.setText( self.personasModel.record( index ).value( "telefono" ).toString() ) @pyqtSlot( unicode ) def on_txtSearch_textChanged( self, searchstring ): """ Cambiar el filtro para el navigation model @param searchstring: Es el contenido por el cual se va a filtrar el modelo de navegación @type searchstring: string """ self.navproxymodel.setFilterFixedString( searchstring )
class FrmKardex( Ui_frmKardex, Base ): ''' Esta clase implementa la funcionalidad para los movimientos de entrada y salida de kardex, en ella el encargado de bodega da cuenta de cuando entra o sale algo de bodega ''' def __init__( self, tiposdoc, parent = None, edit = True ): ''' Constructor ''' super( FrmKardex, self ).__init__( parent ) self.tiposdoc = ",".join( [str( item ) for item in tiposdoc] ) self.edit = edit self.navigationmodel = QSqlQueryModel() self.detailsModel = QSqlQueryModel() self.navproxymodel = QSortFilterProxyModel() self.navproxymodel.setSourceModel( self.navigationmodel ) self.detailsproxymodel = QSortFilterProxyModel() self.detailsproxymodel.setSourceModel( self.detailsModel ) self.tabledetails.setModel( self.detailsproxymodel ) self.tablenavigation.setModel( self.navproxymodel ) self.editmodel = None QTimer.singleShot( 0, self.loadModels ) def updateModels( self ): try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"Existen problemas de conexión "\ + "con la base de datos" ) query = u""" SELECT d.iddocumento, CONCAT_WS(' ',tdc.descripcion, d.ndocimpreso) as 'Documento Referencia', kx.ndocimpreso as 'Numero Kardex', b.nombrebodega as 'Bodega', d.fechacreacion as 'Fecha', kx.observacion as 'Observacion Kardex', d.observacion as 'Observacion Doc', d.idbodega FROM documentos d JOIN tiposdoc tdc ON tdc.idtipodoc = d.idtipodoc JOIN bodegas b ON b.idbodega = d.idbodega JOIN docpadrehijos dpd ON dpd.idpadre = d.iddocumento JOIN documentos kx ON kx.iddocumento = dpd.idhijo AND kx.idtipodoc = %d WHERE d.idtipodoc IN (%s) GROUP BY d.iddocumento """ % ( constantes.IDKARDEX, self.tiposdoc ) self.navigationmodel.setQuery( query ) query = u""" SELECT axd.idarticulo, ad.descripcion as 'Articulo', axd.unidades as 'Unidades', IF(akx.unidades > 0, CONCAT('+',akx.unidades), IFNULL(akx.unidades,0)) as 'Ajuste', axd.iddocumento FROM articulosxdocumento axd JOIN vw_articulosdescritos ad ON ad.idarticulo = axd.idarticulo JOIN documentos d ON axd.iddocumento = d.iddocumento AND d.idtipodoc IN ( %s) JOIN docpadrehijos dph ON dph.idpadre = d.iddocumento JOIN documentos kardex ON kardex.iddocumento = dph.idhijo AND kardex.idtipodoc = %d LEFT JOIN articulosxdocumento akx ON akx.iddocumento = kardex.iddocumento GROUP BY ad.idarticulo, kardex.iddocumento """ % ( self.tiposdoc , constantes.IDKARDEX ) self.detailsModel.setQuery( query ) self.mapper.setModel( self.navproxymodel ) self.mapper.addMapping( self.txtParentPrintedDocumentNumber, NDOCIMPRESO ) self.mapper.addMapping( self.txtPrintedDocumentNumber, NKARDEX ) self.mapper.addMapping( self.dtPicker, FECHA ) self.mapper.addMapping( self.txtWarehouse, NOMBREBODEGA ) self.mapper.addMapping( self.txtKardexObservation, OBSERVACIONK, "plainText" ) self.mapper.addMapping( self.txtDocObservation, OBSERVACION, "plainText" ) # self.tabledetails.horizontalHeader().setStretchLastSection( True ) self.tabledetails.setColumnHidden(0,True) except UserWarning as inst: QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) logging.error( inst ) except Exception as inst: logging.critical( inst ) def updateDetailFilter( self, index ): self.detailsproxymodel.setFilterKeyColumn( IDDOCUMENTOT ) self.detailsproxymodel.setFilterRegExp( "^" + self.navigationmodel.record( index ).value( IDDOCUMENTO ).toString() + "$" ) self.tablenavigation.selectRow( self.mapper.currentIndex() ) def cancel( self ): self.editmodel = None self.tabledetails.setModel( self.detailsproxymodel ) self.status = True @pyqtSlot() @if_edit_model def on_txtKardexObservation_textChanged( self ): self.editmodel.observations = self.txtKardexObservation.toPlainText() def setControls( self, status ): self.tabnavigation.setEnabled( status ) self.actionPrint.setVisible( status ) self.actionGoFirst.setVisible( status ) self.actionGoPrevious.setVisible( status ) self.actionGoNext.setVisible( status ) self.actionGoLast.setVisible( status ) self.actionNew.setVisible( status ) self.actionPreview.setVisible( status ) self.dtPicker.setReadOnly( status ) self.actionCancel.setVisible( not status ) self.actionSave.setVisible( not status ) self.tablenavigation.setColumnHidden( IDDOCUMENTO, True ) self.tablenavigation.setColumnHidden( OBSERVACION, True ) self.tablenavigation.setColumnHidden( OBSERVACIONK, True ) self.tablenavigation.setColumnHidden( BODEGA, True ) self.tabledetails.setColumnHidden( AJUSTE, True ) self.tabledetails.setColumnHidden( IDDOCUMENTOT, True ) if status: self.tabledetails.setEditTriggers( QAbstractItemView.NoEditTriggers ) else: self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers ) self.tabledetails.resizeColumnsToContents() # self.tabledetails.horizontalHeader().setStretchLastSection( True ) self.txtKardexObservation.setReadOnly( status ) # self.tabledetails.horizontalHeader().setStretchLastSection( True ) def newDocument( self ): """ Slot documentation goes here. """ query = QSqlQuery() try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo establecer una conexión"\ + " con la base de datos" ) dlgdoc = dlgSelectDoc( self.tiposdoc ) if dlgdoc.exec_() == QDialog.Accepted: self.editmodel = KardexModel() row = dlgdoc.tblBills.selectionModel().currentIndex().row() self.editmodel.parentId = dlgdoc.filtermodel.index( row, 0 ).data().toInt()[0] self.editmodel.uid = self.user.uid self.editmodel.parentPrinted = dlgdoc.filtermodel.index( row, 1 ).data().toString() self.editmodel.warehouseId = dlgdoc.filtermodel.index( row, 4 ).data().toInt()[0] self.editmodel.warehouseName = dlgdoc.filtermodel.index( row, 2 ).data().toString() self.txtDocObservation.setPlainText( dlgdoc.filtermodel.index( row, 5 ) .data().toString() ) self.txtParentPrintedDocumentNumber.setText( self.editmodel.parentPrinted ) self.txtWarehouse.setText( self.editmodel.warehouseName ) if not query.prepare( """ SELECT axd.idarticulo, vw.descripcion, axd.unidades, cxa.valor FROM articulosxdocumento axd JOIN costosarticulo cxa ON cxa.idarticulo = axd.idarticulo AND cxa.activo = 1 JOIN vw_articulosdescritos vw ON vw.idarticulo = axd.idarticulo WHERE axd.iddocumento = %d """ % self.editmodel.parentId ): raise Exception( "No se pudo preparar la consulta para "\ + "obtener las lineas del documento" ) if not query.exec_(): raise Exception( "No se pudo ejecutar la consulta para"\ + " obtener las lineas del documento" ) if not query.size() > 0: raise Exception( "La consulta para las lineas del "\ + "documento no devolvio nada" ) while query.next(): linea = LineaKardex() linea.itemId = query.value( 0 ).toInt()[0] linea.itemDescription = query.value( 1 ).toString() linea.numdoc = query.value( 2 ).toInt()[0] linea.itemCost = Decimal( query.value( 3 ).toString() ) row = self.editmodel.rowCount() self.editmodel.insertRows( row ) self.editmodel.lines[row] = linea # Cargar el numero de kardex query = QSqlQuery( """ CALL spConsecutivo(%d,NULL); """ % constantes.IDKARDEX ) if not query.exec_(): raise UserWarning( u"No se pudo calcular el numero de"\ + " la devolución" ) query.first() self.editmodel.printedDocumentNumber = query.value( 0 ).toString() self.txtPrintedDocumentNumber.setText( self.editmodel.printedDocumentNumber ) self.status = False self.tabnavigation.setEnabled( False ) self.tabWidget.setCurrentIndex( 0 ) self.tabledetails.setModel( self.editmodel ) delegate = KardexDelegate() self.tabledetails.setItemDelegate( delegate ) self.dtPicker.setDateTime( QDateTime.currentDateTime() ) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) self.tabledetails.resizeColumnsToContents() except UserWarning as inst: QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) logging.warning( inst ) self.cancel() except Exception as inst: QMessageBox.critical( self, qApp.organizationName(), "No se pudo iniciar el documento kardex" ) logging.critical( inst ) self.cancel() finally: if self.database.isOpen(): self.database.close() def updateLabels( self ): pass
class tbFactura( QTabWidget ,Ui_tbFactura ): """ Implementacion de la interfaz grafica para facturas """ web = "facturas.php?doc=" DATE_FORMAT = "dd/MM/yyyy" def __init__( self ): ''' Constructor ''' super( tbFactura, self ).__init__( ) # ESTABLECER LA INTERFAZ AL FORMULARIO self.setupUi(self) # VALIDADOR DE MODO DE EDICION self.readOnly = True self.editmodel = None #ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana) self.categoriesview.headers = ["Descripcion", "Precio", "Unidades","Existencia","","",""] # Crear el modelo para cargar catalogo de clientes self.clientesModel = QSqlQueryModel() # Crear lista de autocompletado para el combo de clientes self.clienteCompleter = QCompleter() # Modelo que carga el catalogo de productos self.existenciaModel = QSqlQueryModel() # Establecer todos los controles en modo de edicion self.setControls( False ) # Crear la conexion a la base de datos self.database = QSqlDatabase.database() self.vistaprevia = False # Cargar los modelos del modo de edicion self.updateEditModels() self.parent = self.parent() def newDocument( self ): """ activar todos los controles, llenar los modelos necesarios, crear el modelo FacturaModel, aniadir una linea a la tabla """ self.readOnly = False if not self.updateEditModels(): return self.status = False self.dtPicker.setDate( self.parentWindow.datosSesion.fecha ) def updateEditModels( self ): """ Este metodo actualiza los modelos usados en el modo edición """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo abrir la conexión "\ + "con la base de datos" ) self.clientesModel.setQuery( """ SELECT idpersona , nombre AS cliente FROM personas WHERE escliente = 1 """) self.cbcliente.setModel( self.clientesModel ) self.cbcliente.setModelColumn( 1 ) self.clienteCompleter.setCaseSensitivity( Qt.CaseInsensitive ) self.clienteCompleter.setModel( self.clientesModel ) self.clienteCompleter.setCompletionColumn( 1 ) self.cbcliente.setCompleter( self.clienteCompleter ) self.editmodel = FacturaModel( ) # Cargar el numero de la factura actual query = QSqlQuery( """ SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d; """ % constantes.IDFACTURA ) if not query.exec_(): raise Exception( "No se pudo obtener el numero de la factura" ) query.first() if query.size()==0: n =1 else: n = str(int(query.value(0)) + 1) self.editmodel.printedDocumentNumber = str(int(query.value(0)) + 1) self.lblnumero.setText(n) # if self.clientesModel.rowCount() == 0: # raise UserWarning( "No existen clientes en la"\ # + " base de datos" ) # return self.clienteCompleter.setModel(self.clientesModel) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setCompleter(self.clienteCompleter) # #Crear el delegado con los articulo y verificar si existen articulos self.existenciaModel.setQuery( QSqlQuery( """ SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos -- WHERE existencia >0 """ ) ) self.categoriesview.update(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos WHERE idprecioproducto IS NOT NULL -- WHERE existencia >0 """) self.categoriesview.expandAll() self.categoriesview.setColumnHidden(3,True) self.categoriesview.setColumnHidden(4,True) self.categoriesview.setColumnWidth(0,150) self.categoriesview.setColumnWidth(1,60) self.categoriesview.setColumnWidth(2,20) self.proxyexistenciaModel = SingleSelectionModel() self.proxyexistenciaModel.setSourceModel( self.existenciaModel ) # self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX ) if self.proxyexistenciaModel.rowCount() == 0: raise UserWarning( "No hay articulos en bodega" ) delegate = FacturaDelegate( self.proxyexistenciaModel ) self.tabledetails.setItemDelegate( delegate ) self.tabledetails.setModel( self.editmodel ) self.tabledetails.setColumnHidden(0,True) # self.editmodel.insertRow(1) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) self.txtobservaciones.setPlainText( "" ) self.dtPicker.setDate(QDate.currentDate().addDays(1)) self.editmodel.fecha = QDate.currentDate().addDays(1) self.cbcliente.setCurrentIndex( -1 ) resultado = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) finally: if self.database.isOpen(): self.database.close() return resultado def addActionsToToolBar( self ): self.actionRefresh = self.createAction( text = "Actualizar", icon = QIcon.fromTheme( 'view-refresh', QIcon( ":/icons/res/view-refresh.png" ) ), slot = self.refresh, shortcut = Qt.Key_F5 ) self.toolBar.addActions( [ self.actionNew, self.actionRefresh, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel, ] ) self.toolBar.addSeparator() self.toolBar.addActions( [ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ] ) def refresh( self ): """ Actualizar los modelos de edición """ if not self.status: if QMessageBox.question( self, qApp.organizationName(), u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.No: return self.updateEditModels() else: if self.updateModels(): QMessageBox.information( None, "Factura", u"Los datos fueron actualizados con éxito" ) def printDocument1(self): html = u"" date = QDate.currentDate().toString(self.DATE_FORMAT) address = Qt.escape("Bario francisco mesa").replace(",","<br>") contact = Qt.escape("Luis Mejia") balance = 5000 html += ("<p align=right><img src=':/logo.png'></p>" "<p> align = right>Greasy hands ltd." "<br>New Lombard Street" "<br>London<br>WC13 4PX<br>%s</p>" "<p>%s</p><p>Dear %s, </p>" "<p>The balance of your account is %s.")% ( date, address, contact, QString("$ %L1").arg(float(balance),0,"f",2)) if balance <0 : html += ("<p><font color =red><b> Please remit the amount owing immediately.</b></font>") else: html += "We are delighted to have done business with you." html += ("</p><p> </p><p>" "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>") transactions = [ (QDate.currentDate(),500), (QDate.currentDate(),500), (QDate.currentDate(),-500), (QDate.currentDate(),500) ] for date, amount in transactions: color, status = "black", "Credit" if amount <0: color, status = "red", "Debid" html += ("<tr>" "<td align= right>%s</td>" "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>" % ( date.toString(self.DATE_FORMAT), status,color, QString("$ %L1").arg(float(abs(amount)), 0, "f",2))) html += ("</table></p><p style='page-break-after=always;'>" "We hope to continue doing business with you</p>") pdialog = QPrintDialog() if pdialog.exec_() == QDialog.Accepted: printer = pdialog.printer() document = QTextDocument() document.setHtml(html) document.print_(printer) def printDocument2(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() headFormat = QTextBlockFormat() headFormat.setAlignment(Qt.AlignLeft) headFormat.setTextIndent( self.printer.pageRect().width()-216) bodyFormat = QTextBlockFormat() bodyFormat.setAlignment(Qt.AlignJustify) lastParaBodyFormat = QTextBlockFormat(bodyFormat) lastParaBodyFormat.setPageBreakPolicy(QTextFormat.PageBreak_AlwaysAfter) rightBodyFormat = QTextBlockFormat() rightBodyFormat.setAlignment(Qt.AlignRight) headCharFormat = QTextCharFormat() headCharFormat.setFont(QFont("Helvetica",10)) bodyCharFormat = QTextCharFormat() bodyCharFormat.setFont(QFont("Times",11)) redBodyCharFormat = QTextCharFormat(bodyCharFormat) redBodyCharFormat.setForeground(Qt.red) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(2) document = QTextDocument() cursor = QTextCursor(document) mainFrame = cursor.currentFrame() page = 1 cursor.insertBlock(headFormat, headCharFormat) for text in ("Greasy Hands Ltd.", "New Lombard Street","London" , "WC13", QDate.currentDate().toString(self.DATE_FORMAT)): cursor.insertBlock(headFormat,headCharFormat) cursor.insertText(text) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Barrio Francisco Meza") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Dear Lyuis") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText(QString("The balance of your account is $ %L1.").arg(float(500.987),0,"f",2)) cursor.insertBlock(bodyFormat,redBodyCharFormat) cursor.insertText("Please remit the amount") cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("Transaction") transactions = [ (QDate.currentDate(),500), (QDate.currentDate(),500), (QDate.currentDate(),-500), (QDate.currentDate(),500) ] table = cursor.insertTable(len(transactions), 3, tableFormat) row = 0 for date, amount in transactions: cellCursor = table.cellAt(row,0).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(date.toString(self.DATE_FORMAT),bodyCharFormat) cellCursor = table.cellAt(row,1).firstCursorPosition() cellCursor.insertText("Credit",bodyCharFormat) cellCursor = table.cellAt(row,2).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(QString("The balance of your account is $ %L1.").arg(float(amount),0,"f",2),redBodyCharFormat) row += 1 cursor.setPosition(mainFrame.lastPosition()) cursor.insertBlock(bodyFormat,bodyCharFormat) cursor.insertText("We hope") document.print_(self.printer) def printDocument(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() self.imprimir(self.printer) self.document.load(self.editmodel) def preview(self): self.vistaprevia = True preview = frmImpresion(self) preview.exec_() def save( self ): """ Guardar el documento actual @rtype: bool """ result = False try: if not self.valid: return False if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar la factura?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos" ) self.editmodel.observaciones = self.txtobservaciones.toPlainText() if not self.editmodel.save(): raise UserWarning( "No se ha podido guardar la factura" ) QMessageBox.information( None, qApp.organizationName() , u"""El documento se ha guardado con éxito""" ) self.readOnly = True self.updateModels() # self.navigate( 'last' ) # self.status = True result = True except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), u"Hubo un error al guardar la factura" ) finally: if self.database.isOpen(): self.database.close() return result # @pyqtSlot(QModelIndex) # def on_categoriesview_doubleClicked(self,index): @pyqtSlot(QModelIndex) def on_categoriesview_activated(self,index): articulo = self.categoriesview.model().asRecord(index) if len(articulo)>0: nuevo = True for i, line in enumerate(self.editmodel.lines): if line.itemId == articulo [5]: nuevo = False fila = i line = self.editmodel.lines[self.editmodel.rowCount()-1] if nuevo: fila = self.editmodel.rowCount() self.editmodel.insertRow(fila) self.parent.saveAct.setEnabled(True) linea = self.editmodel.lines[fila] linea.itemDescription = articulo[0] + " " + articulo [1] linea.itemPrice = Decimal(articulo[2]) linea.itemId = articulo[5] linea.quantityperbox = int(articulo[3]) self.editmodel.lines[fila].quantity += 1 self.editmodel.lines[fila].existencia = int(articulo[4]) - self.editmodel.lines[fila].quantity indice =self.editmodel.index( fila,2) self.editmodel.dataChanged.emit( indice, indice ) indice =self.editmodel.index( fila,3) self.editmodel.dataChanged.emit( indice, indice ) indice =self.editmodel.index( fila,5) self.editmodel.dataChanged.emit( indice, indice ) @pyqtSlot() def on_btneditar_clicked( self ): articulo = dlgArticulo(self) articulo.exec_() self.updateEditModels() @pyqtSlot( int ) def on_cbcliente_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: numero = self.clientesModel.record( index ).value( "idpersona" ) self.editmodel.clienteId = int(numero) if numero is not None else 0 @pyqtSlot( unicode ) def on_cbcliente_editTextChanged( self, text ): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.cliente =str( text) @pyqtSlot( int ) def on_cbvendedor_currentIndexChanged( self, index ): """ asignar proveedor al objeto self.editmodel """ self.editmodel.vendedorId = self.vendedoresModel.record( index ).value( "idpersona" ).toInt()[0] @pyqtSlot( QDate) def on_dtPicker_dateChanged( self, date ): if self.editmodel is not None: self.editmodel.fecha = date @pyqtSlot( bool ) def on_rbcontado_toggled( self, on ): """ Asignar las observaciones al objeto editmodel """ self.editmodel.escontado = 1 if on else 0 def on_txtSearch_textChanged( self, text ): """ Cambiar el filtro de busqueda """ self.filtermodel.setFilterRegExp( text ) def setControls( self, status ): """ @param status: false = editando true = navegando """ # self.actionPrint.setVisible( status ) self.readOnly = status self.txtobservaciones.setReadOnly( status ) # self.actionPreview.setVisible( status ) # self.actionAnular.setVisible( status ) # self.toolBar.setVisible(status) # self.lblnfac.setText( self.editmodel.printedDocumentNumber ) self.swcliente.setCurrentIndex( 0 ) self.lbltotal.setText( "C$ 0.00" ) self.tabledetails.setEditTriggers( QAbstractItemView.AllEditTriggers ) # self.lblanulado.setHidden( True ) self.tabledetails.horizontalHeader().setStretchLastSection(True) self.tabledetails.setColumnHidden( IDARTICULO, True ) self.tabledetails.setColumnHidden( IDDOCUMENTOT, True ) def updateLabels( self ): self.lbltotal.setText( moneyfmt( self.editmodel.total, 2, "C$ " ) ) @property def valid( self ): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.ivaId !=0 self.uid != 0 self.warehouseId != 0 """ if int( self.editmodel.clienteId) == 0 and self.editmodel.cliente == "": QMessageBox.warning( self, qApp.organizationName(), "Por favor elija el cliente" ) self.cbcliente.setFocus() elif self.editmodel.rowCount() == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor agregue algun articulo a la factura" ) else: return True return False def imprimir(self,printer): leftMargin = 72 widthCol = 100 arialFont = QFont("Helvetica",16,3) fuente =QFontMetrics(arialFont) arialLineHeight = fuente.height() fondo = QPixmap(":/images/res/fondo.png") painter = QPainter(printer) pageRect = printer.pageRect() page = 1 painter.save() if self.vistaprevia: painter.drawPixmap(0, 0, 530, 830, fondo) painter.setFont(arialFont) y = 180 x = 35 painter.drawText(x,y,self.editmodel.fecha.toString("dd MM yy")) y = 210 x = 85 painter.drawText(x,y, self.editmodel.cliente) painter.setFont(arialFont) cajasFont = QFont("Helvetica",10,2) x = -5 y = 295 painter.setFont(cajasFont) painter.drawText(x,y - arialLineHeight - 1,"Cajas") for row in self.editmodel.lines: painter.setFont(cajasFont) x = 2 painter.drawText(x,y,row.cantidad()) painter.setFont(arialFont) total = moneyfmt(row.total,2,"") x = 470 - fuente.width(total) painter.drawText(x,y,total) x =310 painter.drawText(x,y,moneyfmt(row.itemPrice,2,"")) x = 30 painter.drawText(x,y,row.unidades()) x = 80 painter.drawText(x,y,row.itemDescription) y+= arialLineHeight total = moneyfmt(self.editmodel.total,2,"") y= 690 x = 470 - fuente.width(total) painter.drawText(x,y,total) painter.setPen(Qt.black) # printer.newPage() painter.restore()
class ChooseMTModelDialog(QDialog, Ui_Dialog): """ Class documentation goes here. """ def __init__(self, parent=None, datamodel=None): """ Constructor """ QDialog.__init__(self, parent) self.setupUi(self) self.model = QSqlQueryModel() self.selTableView.setModel(self.model) self.database = datamodel.getQSqlDatabase() self.updateModel() self.selTableView.hideColumn(0) self.selTableView.hideColumn(5) self.selTableView.hideColumn(6) # Change status and keep the column. QObject.connect(datamodel, SIGNAL("modelInstalled()"), self.on_datamodel_modelInstalled) def updateModel(self): self.model.setQuery( 'SELECT ID, name, srclang, trglang, status, path, mosesini ' 'FROM models ' 'WHERE status = "READY" AND deleted != "True"', self.database) def on_datamodel_recordUpdated(self, bRecord): """Deal with the selection changed problem.""" try: if bRecord: current = self.selTableView.currentIndex() if current and current.row() != -1: self.curSelection = current.row() else: self.curSelection = None else: if self.curSelection is not None: self.selTableView.selectRow(self.curSelection) except Exception as e: print >> sys.stderr, str(e) def on_datamodel_modelInstalled(self): self.updateModel() @pyqtSignature("") def on_buttonBox_accepted(self): """ Slot documentation goes here. """ current = self.selTableView.currentIndex() if not current: doAlert("Please choose a model to start.") return record = self.model.record(current.row()) self.ID = record.value("ID").toString() self.modelName = record.value("name").toString() self.srcLang = record.value('srclang').toString() self.trgLang = record.value('trglang').toString() self.path = record.value("path").toString() self.mosesini = record.value("mosesini").toString() self.accept()
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 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 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 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]
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 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 DatosRecibo( object ): def __init__( self, datosSesion ): object.__init__( self ) self.__documentType = 18 self.clienteId = 0 self.observaciones = "" self.aplicarRet = True self.lineas = [] self.lineasAbonos = [] self.numeroImpreso = '' self.conceptoId = 0 self.datosSesion = datosSesion self.retencionId = 0 self.retencionTasa = Decimal( 0 ) self.retencionNumeroImpreso = '' @property def total( self ): """ """ tmpsubtotal = sum( [linea.monto for linea in self.lineasAbonos] ) return tmpsubtotal if tmpsubtotal > 0 else Decimal( 0 ) @property def subtotal( self ): """ """ tmpsubtotal = sum( [linea.subMonto for linea in self.lineasAbonos] ) return tmpsubtotal if tmpsubtotal > 0 else Decimal( 0 ) @property def totalPagado( self ): """ """ return self.total - self.obtenerRetencion def valid( self, recibo ): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.__idIVA !=0 self.uid != 0 self.warehouseId != 0 """ if int( self.clienteId ) == 0: try: recibo.cbcliente.setFocus() except: pass QMessageBox.information( None, "Guardar Recibo", "No existe un cliente seleccionado" ) elif int( self.conceptoId ) == 0: try: recibo.cbconcepto.setFocus() except: pass QMessageBox.information( None, "Guardar Recibo", "No hay un concepto" ) elif self.aplicarRet and int( self.retencionId ) == 0: recibo.cbtasaret.setFocus() QMessageBox.information( None, "Guardar Recibo", "No hay tasa de retencion" ) elif self.datosSesion.tipoCambioBanco == 0: QMessageBox.information( None, "Guardar Recibo", "no hay un tipo de cambio para la fecha" + self.datosSesion.fecha ) elif int( self.datosSesion.usuarioId ) == 0: raise Exception( "No hay un usuario" ) elif self.printedDocumentNumber == "": raise Exception( "No existe numero de doc impreso" ) else: foo = 0 for line in self.lineas: foo += 1 if not line.valid: recibo.tabledetails.selectRow( foo - 1 ) QMessageBox.information( None, "Guardar Recibo", u"La linea " + str( foo ) + u" de los pagos esta incompleta. " + line.error ) return False if len( self.lineasAbonos ) == 0: QMessageBox.information( None, "Guardar Recibo", u"Por favor elija al menos una factura a la que se realizará el abono" ) return False foo = 0 for line in self.lineasAbonos: foo += 1 if not line.valid: QMessageBox.information( None, "Guardar Recibo", u"La linea " + str( foo ) + u" de las facturas abonadas no es válida" ) return False return True return False @property def retencionValida( self ): subtotal = self.subtotal subtotalC = subtotal * self.datosSesion.tipoCambioBanco return subtotalC > 1000 @property def obtenerRetencion( self ): if self.aplicarRet: if not self.retencionValida: self.aplicarRet = False self.retencionId = 0 return Decimal( 0 ) else: return ( self.subtotal * ( self.retencionTasa / Decimal( 100 ) ) ) else: return Decimal( 0 ) @property def obtenerGanancia( self ): total = self.total retencion = self.obtenerRetencion return Decimal( str( round( ( total + retencion ) * ( self.datosSesion.tipoCambioBanco - self.datosSesion.tipoCambioOficial ), 4 ) ) ) @property def validLines( self ): """ la cantidad de lineas validas que hay en el documento """ foo = 0 for line in self.lineas: if line.valid:foo += 1 return foo def save( self, sinFactura = True ): """ Este metodo guarda el documento actual en la base de datos """ if not self.valid: raise Exception( "El documento a salvar no es valido" ) query = QSqlQuery() try: if sinFactura: if not QSqlDatabase.database().transaction(): raise Exception( u"No se pudo comenzar la transacción" ) fechaCreacion = self.datosSesion.fecha.toString( 'yyyyMMdd' ) + QDateTime.currentDateTime().toString( "hhmmss" ) #INSERTAR RECIBO query.prepare( """ INSERT INTO documentos (ndocimpreso,fechacreacion,idtipodoc, observacion,total,idtipocambio,idconcepto,idcaja) VALUES ( :ndocimpreso,:fechacreacion,:idtipodoc,:observacion,:total,:idtc,:concepto,:caja) """ ) query.bindValue( ":ndocimpreso", self.printedDocumentNumber ) query.bindValue( ":fechacreacion", fechaCreacion ) query.bindValue( ":idtipodoc", self.__documentType ) query.bindValue( ":observacion", self.observaciones ) totalPagado = self.totalPagado query.bindValue( ":total", totalPagado.to_eng_string() ) query.bindValue( ":idtc", self.datosSesion.tipoCambioId ) query.bindValue( ":concepto", self.conceptoId ) query.bindValue( ":caja", self.datosSesion.cajaId ) if not query.exec_(): raise Exception( "No se pudo insertar el recibo" ) insertedId = query.lastInsertId().toString() #INSERTAR LA RELACION CON LA SESION DE CAJA query.prepare( """ INSERT INTO docpadrehijos (idpadre,idhijo) VALUES (:idsesion,:idrecibo) """ ) query.bindValue( ":idsesion", self.datosSesion.sesionId ) query.bindValue( ":idrecibo", insertedId ) if not query.exec_(): raise Exception( "No se Inserto la relacion entre la sesion de caja y el recibo" ) #INSERTAR LA RELACION CON El USUARIO y EL CLIENTE query.prepare( "INSERT INTO personasxdocumento (iddocumento,idpersona,idaccion) VALUES" + "(" + insertedId + ",:iduser,:autor)," "(" + insertedId + ",:idcliente,:cliente)" ) query.bindValue( ":iduser", self.datosSesion.usuarioId ) query.bindValue( ":autor", constantes.AUTOR ) query.bindValue( ":idcliente", self.clienteId ) query.bindValue( ":usuario", constantes.CLIENTE ) if not query.exec_(): raise Exception( "No se Inserto la relacion entre el recibo y las personas" ) #INSERTAR LOS TIPOS DE PAGO if len( self.lineas ) == 0: raise Exception( "Deben existir pagos" ) i = 1 for linea in self.lineas: # print insertedId + "-" + str(linea.pagoId) + "-" + str(linea.monedaId) linea.save( insertedId, i ) i = i + 1 #INSERTAR los abonos i = 0 if len( self.lineasAbonos ) == 0: raise Exception( "Deben existir abonos" ) for l in self.lineasAbonos: l.save( insertedId, i ) i = i + 1 #VERIFICO SI se aplicara la retencion if self.aplicarRet : #INSERTAR EL DOCUMENTO RETENCION CON EL TOTAL EN NEGATIVO, PORQUE ESTA SALIENDO DE CAJA query.prepare( """ INSERT INTO documentos (ndocimpreso,fechacreacion,idtipodoc,total,idtipocambio,idconcepto) VALUES ( :ndocimpreso,:fechacreacion,:idtipodoc,:total,:idtc,:concepto) """ ) query.bindValue( ":ndocimpreso", self.retencionNumeroImpreso ) query.bindValue( ":fechacreacion", fechaCreacion ) query.bindValue( ":idtipodoc", constantes.IDRETENCION ) query.bindValue( ":total", self.obtenerRetencion.to_eng_string() ) query.bindValue( ":idtc", self.datosSesion.tipoCambioId ) query.bindValue( ":concepto", self.conceptoId ) if not query.exec_(): raise Exception( "No se Inserto la retencion" ) idret = query.lastInsertId().toString() query.prepare( "INSERT INTO docpadrehijos (idpadre,idhijo) VALUES" + "(:idsesion," + idret + ")," + "(:idrecibo," + idret + ")" ) query.bindValue( ":idsesion", self.datosSesion.sesionId ) query.bindValue( ":idrecibo", insertedId ) if not query.exec_(): raise Exception( "No se Inserto la relacion entre la retencion y el recibo" ) # INSERTAR EL ID DEL COSTO RETENCION query.prepare( """ INSERT INTO costosxdocumento (iddocumento, idcostoagregado) VALUES( :iddocumento, :idcostoagregado ) """ ) query.bindValue( ":iddocumento", insertedId ) query.bindValue( ":idcostoagregado", self.retencionId ) if not query.exec_(): raise Exception( "el costo Retencion NO SE INSERTO" ) #manejar las cuentas contables tasa = self.datosSesion.tipoCambioOficial movAbonoDeCliente( insertedId, self.total * tasa, self.obtenerRetencion * tasa, self.obtenerGanancia ) if sinFactura: if not QSqlDatabase.database().commit(): raise Exception( "No se pudo hacer commit" ) except Exception as inst: QSqlDatabase.database().rollback() return False return True def cargarRetenciones( self, cbtasaret ): # Rellenar el combobox de las retenciones self.retencionModel = QSqlQueryModel() self.retencionModel.setQuery( """ SELECT idcostoagregado, FORMAT(valorcosto,0) as tasa FROM costosagregados WHERE (idtipocosto=%d OR idtipocosto =%d) AND activo=1 ORDER BY valorcosto desc; """ % ( constantes.RETENCIONPROFESIONALES, constantes.RETENCIONFUENTE ) ) cbtasaret.setModel( self.retencionModel ) cbtasaret.setModelColumn( 1 ) cbtasaret.setCurrentIndex( -1 ) self.retencionId = 0 def cargarNumeros( self, recibo ): # Cargar el numero de el Recibo actual idrec = str( constantes.IDRECIBO ) idret = str( constantes.IDRETENCION ) query = QSqlQuery( "CALL spConsecutivo(" + idrec + ",null)" ) if not query.exec_(): print( query.lastError().text() ) query.first() n = query.value( 0 ).toString() recibo.lblnrec.setText( n ) self.printedDocumentNumber = n query = QSqlQuery( "CALL spConsecutivo(" + idret + ",null)" ) if not query.exec_(): print( query.lastError().text() ) query.first() n = query.value( 0 ).toString() recibo.lblnreten.setText( n ) self.retencionNumeroImpreso = n def tasaRetencionCambio( self, _recibo, index ): self.retencionId = self.retencionModel.record( index ).value( "idcostoagregado" ).toInt()[0] value = self.retencionModel.record( index ).value( "tasa" ).toString() self.retencionTasa = Decimal( value if value != "" else 0 )
class dlgmovimientosbancarios (QDialog,Ui_dlgMovimientosBancarios): def __init__( self, parent ): super( dlgmovimientosbancarios, self ).__init__( parent ) self.conceptosModel = QSqlQueryModel() self.setupUi( self ) self.database = QSqlDatabase.database() self.proxymodel = QSortFilterProxyModel() self.editmodel = MovimientosBancariosModel() fecha = self.parent().editmodel.fechaConciliacion self.dtPicker.setMaximumDate(fecha) self.dtPicker.setMinimumDate(QDate(fecha.year(),fecha.month(),1)) self.cbtipodoc.addItem(u"Nota de Crédito") self.cbtipodoc.addItem(u"Nota de Débito") self.conceptosModel.setQuery( """ SELECT idconcepto, descripcion,idtipodoc FROM conceptos c WHERE idtipodoc in (%d,%d ); """ %(constantes.IDNOTACREDITO,constantes.IDND) ) self.proxymodel.setSourceModel(self.conceptosModel) self.proxymodel.setFilterKeyColumn(2) self.proxymodel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.cbconcepto.setModel(self.proxymodel) self.cbconcepto.setModelColumn(1) self.buttonBox.rejected.connect( self.reject ) self.buttonBox.accepted.connect( self.aceptar ) self.editmodel.tipoDoc = constantes.IDDEPOSITO self.cuentasDelegate = AccountsSelectorDelegate( QSqlQuery( """ SELECT c.idcuenta, c.codigo, c.descripcion FROM cuentascontables c JOIN cuentasxdocumento cd ON c.idcuenta = cd.idcuenta WHERE c.idcuenta in (%d,%d,%d) """ %(constantes.CAJAGENERAL,constantes.CAJACHICA, constantes.CAPITAL) ) ) self.editmodel.insertRow( 1 ) self.editmodel.lines[0].itemId = parent.editmodel.idCuentaContable self.editmodel.lines[0].code = parent.txtcuenta.text() self.editmodel.lines[0].name = parent.txtcuenta.toolTip() self.editmodel.insertRow( 1 ) self.editmodel.fechaDoc = QDateTime.currentDateTime() self.editmodel.autorId = parent.user.uid # Crea un edit delegate para las cuentas self.tabledetails.setItemDelegate( self.cuentasDelegate ) self.tabledetails.setModel( self.editmodel ) self.tabledetails.setEditTriggers( QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed | QAbstractItemView.DoubleClicked ) self.tabledetails.setColumnHidden(0,False) @pyqtSlot( int ) def on_cbtipodoc_currentIndexChanged(self,index): self.editmodel.tipoDoc = constantes.IDNOTACREDITO if self.cbtipodoc.currentIndex()== 0 else constantes.IDND self.proxymodel.setFilterRegExp("%d"%self.editmodel.tipoDoc) @pyqtSlot( int ) def on_cbconcepto_currentIndexChanged(self,index): self.editmodel.conceptoId =self.conceptosModel.record( index ).value( "idconcepto" ).toInt()[0] def aceptar(self): """ Guardar el documento actual """ self.editmodel.totalDoc = self.editmodel.lines[0].amount self.editmodel.tipoDoc = constantes.IDNOTACREDITO if self.cbtipodoc.currentIndex()== 0 else constantes.IDND if self.editmodel.valid: # Base.save( self, True ) if QMessageBox.question( self, qApp.organizationName(), u"¿Desea guardar el documento?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: if self.editmodel.save(): QMessageBox.information( self, qApp.organizationName(), u"El documento se ha guardado con éxito" ) else: QMessageBox.critical( self, qApp.organizationName(), "Ha ocurrido un error al guardar el documento" ) self.accept() else: QMessageBox.information(None, "Datos Incompletos", self.editmodel.mensajeError)
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()
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 ChooseMTModelDialog(QDialog, Ui_Dialog): """ Class documentation goes here. """ def __init__(self, parent=None, datamodel=None): """ Constructor """ QDialog.__init__(self, parent) self.setupUi(self) self.model = QSqlQueryModel() self.selTableView.setModel(self.model) self.database = datamodel.getQSqlDatabase() self.updateModel() self.selTableView.hideColumn(0) self.selTableView.hideColumn(5) self.selTableView.hideColumn(6) # Change status and keep the column. QObject.connect( datamodel, SIGNAL("modelInstalled()"), self.on_datamodel_modelInstalled) def updateModel(self): self.model.setQuery( 'SELECT ID, name, srclang, trglang, status, path, mosesini ' 'FROM models ' 'WHERE status = "READY" AND deleted != "True"', self.database) def on_datamodel_recordUpdated(self, bRecord): """Deal with the selection changed problem.""" try: if bRecord: current = self.selTableView.currentIndex() if current and current.row() != -1: self.curSelection = current.row() else: self.curSelection = None else: if self.curSelection is not None: self.selTableView.selectRow(self.curSelection) except Exception as e: print >> sys.stderr, str(e) def on_datamodel_modelInstalled(self): self.updateModel() @pyqtSignature("") def on_buttonBox_accepted(self): """ Slot documentation goes here. """ current = self.selTableView.currentIndex() if not current: doAlert("Please choose a model to start.") return record = self.model.record(current.row()) self.ID = record.value("ID").toString() self.modelName = record.value("name").toString() self.srcLang = record.value('srclang').toString() self.trgLang = record.value('trglang').toString() self.path = record.value("path").toString() self.mosesini = record.value("mosesini").toString() self.accept()
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
class Helferlein(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) # Oberfläche abbilden: self.ui = uic.loadUi("ui_helferlein.ui") self.ui.setWindowIcon(QtGui.QIcon('helferlein.png')) #self.db = QSqlDatabase.addDatabase("QMYSQL") self.db = QSqlDatabase.addDatabase("QSQLITE3") self.db.setHostName("localhost") self.db.setDatabaseName("helferlein") self.user = "******" self.password = "******" if self.db.open(self.user, self.password): print "DB Verbindung" #self.init_db() else: print "Verbindung konnte nicht hergestellt werden" self.sql_model_namensliste = QSqlQueryModel(self) self.sql_model_fehlzeiten = QSqlQueryModel(self) self.ui.tableView_schuelernamen.setModel(self.sql_model_namensliste) self.ui.tableView_fehlzeiten.setModel(self.sql_model_fehlzeiten) # Argumente übergeben if len(sys.argv) > 1: self.filename = sys.argv[1] f = open(self.filename,'rb') self.schuelerliste = pickle.load(f) f.close() for schueler in self.schuelerliste.values(): self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname) self.ui.listWidget.sortItems(0) else: self.filename = '' self.schuelerliste = {} # Grundeinstellungen: self.ui.dateEdit.setDate(QtCore.QDate.currentDate()) self.ui.dateEdit_2.setDate(QtCore.QDate.currentDate()) self.ui.dateEdit_3.setDate(QtCore.QDate.currentDate()) self.ui.dateEdit_4.setDate(QtCore.QDate.currentDate()) self.ui.comboBox_stufenwahl.currentIndexChanged.connect(self.stufenwahl) self.ui.show() # Connects: # Menü self.ui.actionStufe_importieren.triggered.connect(self.stufe_importieren) self.ui.action_ffnen.triggered.connect(self.datei_oeffnen) self.ui.actionSpeichern.triggered.connect(self.datei_speichern) self.ui.actionSpeichern_unter.triggered.connect(self.datei_speichern_unter) self.ui.actionSch_ler_l_schen.triggered.connect(self.schueler_loeschen) self.ui.actionSch_ler_hinzuf_gen.triggered.connect(self.schueler_anlegen) self.ui.actionKrankmeldungen.triggered.connect(self.zeige_krankmeldungen) self.ui.actionBeurlaubungen.triggered.connect(self.zeige_beurlaubungen) self.ui.actionKlausur_Attest.triggered.connect(self.zeige_klausur_attest) self.ui.actionDefizite_suchen.triggered.connect(self.suche_defizite) self.ui.actionKlausurplan_konvertieren.triggered.connect(self.klausurplan_konvertieren) self.ui.tableView_schuelernamen.activated.connect(self.schueler_auswahl) self.ui.tableView_schuelernamen.clicked.connect(self.schueler_auswahl) self.ui.lineEdit.textChanged.connect(self.suche) self.ui.pushButton_7.clicked.connect(self.heutiges_datum_setzen) # Krankmeldungen self.ui.pushButton.clicked.connect(self.krankmeldung_speichern) self.ui.lineEdit_2.returnPressed.connect(self.krankmeldung_speichern) self.ui.pushButton_4.clicked.connect(self.eintrag_loeschen_krank) self.ui.tableView_fehlzeiten.clicked.connect(self.krankmeldung_aufrufen) # Beurlaubungen self.ui.pushButton_2.clicked.connect(self.beurlaubung_speichern) self.ui.lineEdit_3.returnPressed.connect(self.beurlaubung_speichern) self.ui.pushButton_5.clicked.connect(self.eintrag_loeschen_beurlaubung) self.ui.tableWidget_2.cellClicked.connect(self.beurlaubung_aufrufen) # Bemerkungen self.ui.pushButton_3.clicked.connect(self.bemerkung_speichern) #self.ui.lineEdit_4.returnPressed.connect(self.bemerkung_speichern) self.ui.pushButton_6.clicked.connect(self.eintrag_loeschen_bemerkung) self.ui.tableWidget_3.cellClicked.connect(self.bemerkung_aufrufen) self.ui.calendarWidget.selectionChanged.connect(self.datum_geaendert) #self.ui.tableWidget.cellChanged.connect(self.zeile_geaendert_krank) # DB-Methoden ############################################################### def init_db(self): print "here" sql_query = QSqlQuery('''SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'helferlein';''', self.db) size = sql_query.size() print size if size == 0: print "db anlegen" sql_query = QSqlQuery("CREATE DATABASE helferlein;", self.db) print "tabelle schueler anlegen" sql_query = QSqlQuery('''CREATE TABLE SCHUELER ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, Name CHAR(100), Vorname CHAR(100), Stufe CHAR(2));''', self.db) print "tabelle fehlzeit anlegen" sql_query.prepare('''CREATE TABLE FEHLZEIT ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, schueler_id INT, Grund CHAR(100), Beginn CHAR(10), Ende CHAR(10), Stunden INT, ist_Beurlaubung INT, Attest INT, klausur_verpasst INT, Schuljahr CHAR(10));''') sql_query.exec_() def create_db(self): self.db.setDatabaseName(FILENAME_DB) ok = self.db.open() if ok: sql_query = QSqlQuery() # Menü-Methoden: def stufe_importieren(self): filename = QtGui.QFileDialog.getOpenFileName(self, u'CVS-Datei öffnen','.') namens_liste = [[col.strip() for col in row.split(";")] for row in codecs.open(filename, encoding="iso-8859-15")] sql_query = QSqlQuery() sql_query.prepare('''INSERT INTO SCHUELER(NAME, VORNAME, STUFE) VALUES(:name,:vorname,:stufe)''') for name, vorname, stufe in namens_liste: sql_query.bindValue(':name',name) sql_query.bindValue(':vorname', vorname) sql_query.bindValue(':stufe', stufe) sql_query.exec_() def datei_oeffnen(self): self.filename = QtGui.QFileDialog.getOpenFileName(self, u'Datei öffnen','.') f = open(self.filename,'rb') self.schuelerliste = pickle.load(f) f.close() self.ui.listWidget.clear() for schueler in self.schuelerliste.values(): self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname) self.ui.listWidget.sortItems(0) def datei_speichern(self): f = open(self.filename,'wb') pickle.dump(self.schuelerliste,f) f.close() def datei_speichern_unter(self): filename = QtGui.QFileDialog.getSaveFileName(self, u'Namen der Datei angeben','.') f = open(filename,'wb') pickle.dump(self.schuelerliste,f) f.close() def schueler_loeschen(self): if self.ui.label_3.text(): name, vorname = self.ui.label_3.text().split(', ') reply = QtGui.QMessageBox.question(self, "Achtung!", "Soll %s, %s wirklich gelöscht werden?" % (name,vorname), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: del self.schuelerliste[(vorname,name)] self.ui.listWidget.clear() for schueler in self.schuelerliste.values(): self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname) self.ui.listWidget.sortItems(0) self.datei_speichern() self.ui.label_3.setText("") self.ui.label_10.setText("") self.ui.label_16.setText("") else: MESSAGE = u"<p>Bitte erst einen Schüler aus der Liste auswählen</p>" reply = QtGui.QMessageBox.information(self, "Achtung!", MESSAGE) def schueler_anlegen(self): dialog_anlegen = Dialog_Schueler_Anlegen(self) dialog_anlegen.ui.setWindowTitle(u'Schüler/in hinzufügen') if dialog_anlegen.ui.exec_() == 1: name = dialog_anlegen.ui.lineEdit_name.text() vorname = dialog_anlegen.ui.lineEdit_vorname.text() stufe = dialog_anlegen.ui.spinBox_stufe.value() schueler = Schueler(vorname, name, stufe) if schueler not in self.schuelerliste: self.schuelerliste[(vorname, name)] = schueler self.ui.listWidget.clear() for schueler in self.schuelerliste.values(): self.ui.listWidget.addItem(schueler.name + ', ' + schueler.vorname) self.ui.listWidget.sortItems(0) self.datei_speichern() self.ui.label_3.setText("") self.ui.label_10.setText("") self.ui.label_16.setText("") # Fenster-Methoden: def stufenwahl(self, index): print "stufenwahl", index query = '''SELECT id, Name, Vorname FROM SCHUELER WHERE Stufe='{}' ORDER BY Name;'''.\ format(self.ui.comboBox_stufenwahl.itemText(index)) print query sql_query = QSqlQuery(query) self.sql_model_namensliste.setQuery(sql_query) sql_query.exec_() self.ui.tableView_schuelernamen.hideColumn(0) #don't show id def schueler_auswahl(self, index): self.schueler_id = index.sibling(index.row(),0).data().toString() name = index.sibling(index.row(),1).data().toString() vorname = index.sibling(index.row(),2).data().toString() self.ui.label_3.setText(u'{}, {}'.format(name, vorname)) self.ui.label_10.setText(u'{}, {}'.format(name, vorname)) self.ui.label_16.setText(u'{}, {}'.format(name, vorname)) self.tabelle_krank_aktualisieren() def heutiges_datum_setzen(self): self.ui.calendarWidget.setSelectedDate(QtCore.QDate.currentDate()) def tabelle_krank_aktualisieren(self): query_string = '''SELECT id, Beginn, Ende, Attest, klausur_verpasst as Klausur, Grund FROM FEHLZEIT WHERE FEHLZEIT.schueler_id={} AND ist_beurlaubung = '0'; '''.format(self.schueler_id) print query_string sql_query = QSqlQuery(query_string) self.sql_model_fehlzeiten.setQuery(sql_query) self.ui.tableView_fehlzeiten.hideColumn(0) #don't show id sql_query.exec_() self.ui.tableView_fehlzeiten.resizeColumnsToContents() self.ui.tableView_fehlzeiten.horizontalHeader().setStretchLastSection(True) def tabelle_beurlaubung_aktualisieren(self,schueler): self.ui.tableWidget_2.setRowCount(len(schueler.beurlaubungen.keys())) zeile = 0 for eintrag in sorted(schueler.beurlaubungen.keys(),reverse=True): liste = schueler.beurlaubungen[eintrag] liste0 = [eintrag.toString("dd.MM.yyyy"), liste[0].toString("dd.MM.yyyy"), str(liste[1]), liste[2]] for spalte in range(4): item = QtGui.QTableWidgetItem(liste0[spalte]) self.ui.tableWidget_2.setItem(zeile, spalte, item); zeile += 1 self.ui.tableWidget_2.resizeColumnsToContents() self.ui.tableWidget_2.horizontalHeader().setStretchLastSection(True) def tabelle_bemerkung_aktualisieren(self,schueler): self.ui.tableWidget_3.setRowCount(len(schueler.bemerkungen.keys())) zeile = 0 for eintrag in sorted(schueler.bemerkungen.keys(),reverse=True): aktennotiz = ('ja' if schueler.bemerkungen[eintrag][1] else 'nein') bemerkung = schueler.bemerkungen[eintrag][0] liste0 = [eintrag.toString("dd.MM.yyyy"),aktennotiz, bemerkung] for spalte in range(3): item = QtGui.QTableWidgetItem(liste0[spalte]) self.ui.tableWidget_3.setItem(zeile, spalte, item); zeile += 1 self.ui.tableWidget_3.resizeColumnsToContents() self.ui.tableWidget_3.horizontalHeader().setStretchLastSection(True) self.ui.plainTextEdit.clear() def ui_zuruecksetzen(self): self.ui.lineEdit.clear() self.ui.lineEdit_2.clear() self.ui.lineEdit_3.clear() #self.ui.lineEdit_4.clear() self.ui.plainTextEdit.clear() self.ui.checkBox.setChecked(False) self.ui.checkBox_2.setChecked(False) self.ui.checkBox_3.setChecked(False) self.ui.spinBox.setValue(0) self.ui.calendarWidget.setSelectedDate(QtCore.QDate.currentDate()) def suche(self,text): self.ui.listWidget.clear() for schueler in self.schuelerliste: if schueler[0].contains(text,0) or schueler[1].contains(text,0): s = self.schuelerliste[schueler] self.ui.listWidget.addItem(s.name + ', ' + s.vorname) self.ui.listWidget.sortItems(0) def datum_geaendert(self): datum_aktuell = self.ui.calendarWidget.selectedDate() self.ui.dateEdit.setDate(datum_aktuell) self.ui.dateEdit_2.setDate(datum_aktuell) self.ui.dateEdit_3.setDate(datum_aktuell) self.ui.dateEdit_4.setDate(datum_aktuell) def krankmeldung_speichern(self): self.schuljahr = '2013/14' datum_von = self.ui.dateEdit.date().toString("dd.MM.yyyy") datum_bis = self.ui.dateEdit_2.date().toString("dd.MM.yyyy") grund = (unicode(self.ui.lineEdit_2.text()) if self.ui.lineEdit_2.text() else u'-') attest = (u'ja' if self.ui.checkBox.isChecked() else u'nein') klausur = (u'ja' if self.ui.checkBox_2.isChecked() else u'nein') sql_query = QSqlQuery() query_string = '''INSERT INTO FEHLZEIT (schueler_id, Grund, Beginn, Ende, Attest, klausur_verpasst, ist_beurlaubung, schuljahr) VALUES({},'{}','{}','{}','{}','{}','0','{}');'''.format(self.schueler_id, grund, datum_von, datum_bis, attest, klausur, self.schuljahr) #print query_string sql_query.prepare(query_string) sql_query.exec_() self.ui_zuruecksetzen() self.tabelle_krank_aktualisieren() def eintrag_loeschen_krank(self): selected_items = self.ui.tableView_fehlzeiten.selectionModel().selection().indexes() if selected_items: index = selected_items[0] zeile = index.row() fehlzeit_id = index.sibling(zeile,0).data().toString() reply = QtGui.QMessageBox.question(self, "Achtung!", u"Soll die markierte Zeile wirklich gelöscht werden?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: print "Zeile löschen", fehlzeit_id sql_query = QSqlQuery('''DELETE FROM FEHLZEIT WHERE id = {}'''.format(fehlzeit_id)) sql_query.exec_() self.tabelle_krank_aktualisieren() else: QtGui.QMessageBox.information(self, "Achtung!", "Bitte erst eine Zeile markieren!") def krankmeldung_aufrufen(self,index): zeile = index.row() sql_record = self.sql_model_fehlzeiten.record(zeile) beginn = sql_record.value('Beginn').toString() ende = sql_record.value('Ende').toString() attest = sql_record.value('Attest').toString() == 'ja' klausur = sql_record.value('Klausur').toString() == 'ja' grund = sql_record.value('Grund').toString() self.ui.dateEdit.setDate(QtCore.QDate.fromString(beginn,"dd.MM.yyyy")) self.ui.dateEdit_2.setDate(QtCore.QDate.fromString(ende,"dd.MM.yyyy")) self.ui.checkBox.setChecked(attest) self.ui.checkBox_2.setChecked(klausur) self.ui.lineEdit_2.setText(grund) def beurlaubung_speichern(self): name, vorname = self.ui.label_10.text().split(', ') schueler = self.schuelerliste[(vorname,name)] datum_von = self.ui.dateEdit_3.date() datum_bis = self.ui.dateEdit_4.date() grund = (self.ui.lineEdit_3.text() if self.ui.lineEdit_3.text() else u'-') anzahl_stunden = self.ui.spinBox.value() schueler.beurlaubungen[datum_von]=[datum_bis,anzahl_stunden,grund] self.ui_zuruecksetzen() self.tabelle_beurlaubung_aktualisieren() self.datei_speichern() def beurlaubung_aufrufen(self,zeile,spalte): self.ui.dateEdit_3.setDate(QtCore.QDate.fromString(self.ui.tableWidget_2.item(zeile,0).text(),"dd.MM.yyyy")) self.ui.dateEdit_4.setDate(QtCore.QDate.fromString(self.ui.tableWidget_2.item(zeile,1).text(),"dd.MM.yyyy")) self.ui.spinBox.setValue(int(self.ui.tableWidget_2.item(zeile,2).text())) self.ui.lineEdit_3.setText(self.ui.tableWidget_2.item(zeile,3).text()) def bemerkung_speichern(self): name, vorname = self.ui.label_16.text().split(', ') schueler = self.schuelerliste[(vorname,name)] datum = self.ui.calendarWidget.selectedDate() bemerkung = self.ui.plainTextEdit.document().toPlainText() if not bemerkung: QtGui.QMessageBox.information(self,u"Achtung!", u"Bitte erst eine Bemerkung eingeben!") else: schueler.bemerkungen[datum]=[bemerkung,self.ui.checkBox_3.isChecked()] self.tabelle_bemerkung_aktualisieren(schueler) self.datei_speichern() if self.ui.checkBox_3.isChecked(): printer = QtGui.QPrinter() printer.setPaperSize(QtGui.QPrinter.A4) kopfzeile = u'Aktennotiz von ' + vorname + ' ' + name + u' am ' + datum.toString("dd.MM.yyyy") + ':\n\n' #kopfzeile = u'<b>Aktennotiz von ' + vorname + ' ' + name + u' am ' + datum.toString("dd.MM.yyyy") + ':</b><br /><br />' doc = QtGui.QTextDocument(kopfzeile + bemerkung) #doc.setHtml(kopfzeile + bemerkung) doc.print_(printer) self.ui_zuruecksetzen() def bemerkung_aufrufen(self,zeile,spalte): #print zeile, spalte self.ui.calendarWidget.setSelectedDate(QtCore.QDate.fromString(self.ui.tableWidget_3.item(zeile,0).text(),"dd.MM.yyyy")) self.ui.plainTextEdit.setPlainText(self.ui.tableWidget_3.item(zeile,2).text()) if self.ui.tableWidget_3.item(zeile,1).text()=='ja': self.ui.checkBox_3.setChecked(True) else: self.ui.checkBox_3.setChecked(False) def eintrag_loeschen_beurlaubung(self): name, vorname = self.ui.label_10.text().split(', ') schueler = self.schuelerliste[(vorname,name)] i, ok = QtGui.QInputDialog.getInteger(self, u"Zeile löschen", u"Welche Zeile soll gelöscht werden?",1,1 ,len(schueler.beurlaubungen.keys()), 1) if ok: datum = QtCore.QDate.fromString(self.ui.tableWidget_2.item(i-1,0).text(),"dd.MM.yyyy") del schueler.beurlaubungen[datum] self.tabelle_beurlaubung_aktualisieren(schueler) self.datei_speichern() def eintrag_loeschen_bemerkung(self): name, vorname = self.ui.label_16.text().split(', ') schueler = self.schuelerliste[(vorname,name)] i, ok = QtGui.QInputDialog.getInteger(self, u"Zeile löschen", u"Welche Zeile soll gelöscht werden?",1,1 ,len(schueler.bemerkungen.keys()), 1) if ok: datum = QtCore.QDate.fromString(self.ui.tableWidget_3.item(i-1,0).text(),"dd.MM.yyyy") del schueler.bemerkungen[datum] self.tabelle_bemerkung_aktualisieren(schueler) self.datei_speichern() def zeile_geaendert_krank(self,zeile,spalte): print self.ui.tableWidget.item(zeile,spalte).text() if self.ui.tableWidget.item(zeile,spalte).text() != '': name, vorname = self.ui.label_3.text().split(', ') schueler = self.schuelerliste[(vorname,name)] datum = QtCore.QDate.fromString(self.ui.tableWidget.item(zeile,0).text(),"dd.MM.yyyy") datum_bis = QtCore.QDate.fromString(self.ui.tableWidget.item(zeile,1).text(),"dd.MM.yyyy") attest = self.ui.tableWidget.item(zeile,2).text() grund = self.ui.tableWidget.item(zeile,3).text() schueler.krankmeldungen[datum]=[datum_bis,attest,grund] self.datei_speichern() #Statistiken def zeige_krankmeldungen(self): dialog_krank = Dialog_Tabelle(self) dialog_krank.ui.setWindowTitle(u'Krankmeldungen') dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste)) dialog_krank.ui.tableWidget.setColumnCount(2) dialog_krank.ui.tableWidget.setHorizontalHeaderLabels([u'Name, Vorname',u'Tage krank']) schueler_krank = [] for schueler in self.schuelerliste.values(): tage = 0 for datum in schueler.krankmeldungen.keys(): tage += datum.daysTo(schueler.krankmeldungen[datum][0])+1 schueler_krank.append([schueler.name+ ', ' + schueler.vorname,str(tage)]) zeile = 0 for eintrag in sorted(schueler_krank, key= lambda schueler : int(schueler[1]), reverse=True): for spalte in range(2): item = QtGui.QTableWidgetItem(eintrag[spalte]) if spalte == 1: item.setTextAlignment(4) dialog_krank.ui.tableWidget.setItem(zeile, spalte, item); zeile += 1 dialog_krank.ui.tableWidget.resizeColumnsToContents() dialog_krank.ui.tableWidget.resizeRowsToContents() dialog_krank.ui.tableWidget.horizontalHeader().setStretchLastSection(True) def zeige_beurlaubungen(self): dialog_krank = Dialog_Tabelle(self) dialog_krank.ui.setWindowTitle(u'Beurlaubungen') dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste)) dialog_krank.ui.tableWidget.setColumnCount(2) dialog_krank.ui.tableWidget.setHorizontalHeaderLabels([u'Name, Vorname',u'Stunden beurlaubt']) schueler_beurlaubt = [] for schueler in self.schuelerliste.values(): stunden = 0 for datum in schueler.beurlaubungen: stunden += schueler.beurlaubungen[datum][1] schueler_beurlaubt.append([schueler.name+ ', ' + schueler.vorname,str(stunden)]) zeile = 0 for eintrag in sorted(schueler_beurlaubt, key= lambda schueler : int(schueler[1]), reverse=True): for spalte in range(2): item = QtGui.QTableWidgetItem(eintrag[spalte]) if spalte == 1: item.setTextAlignment(4) dialog_krank.ui.tableWidget.setItem(zeile, spalte, item); zeile += 1 dialog_krank.ui.tableWidget.resizeColumnsToContents() def zeige_klausur_attest(self): dialog_krank = Dialog_Tabelle(self) dialog_krank.ui.setWindowTitle(u'versäumte Klausuren') dialog_krank.ui.tableWidget.setRowCount(len(self.schuelerliste)) dialog_krank.ui.tableWidget.setColumnCount(3) def suche_defizite(self): MESSAGE = u"<p>Die Eingabedatei muss im CSV-Format (als Trennzeichen Komma) vorliegen.</p>" \ u"<p>Die Ausgabedatei wird in demselben Verzeichnis erzeugt, wo die Eingabedatei liegt.\ Sie hat den gleichen Namen mit dem Zusatz '_defizite'.\<p>Sollte etwas nicht funktionieren, frag Boris ;).</p>" reply = QtGui.QMessageBox.information(self, "Achtung!", MESSAGE) if reply == QtGui.QMessageBox.Ok: items = ("Noten", "Punkte") item, ok = QtGui.QInputDialog.getItem(self, "Abfrage", "Wie sind die Noten eingeben?\nAls...", items, 0, False) if ok and item: print item csv_ein = QtGui.QFileDialog.getOpenFileName(self, u'CSV-Datei öffnen','.') if csv_ein: finde_defizite(str(csv_ein), str(item)) def klausurplan_konvertieren(self): MESSAGE = u"<p>Die Eingabedatei muss im CSV-Format vorliegen\ Es dürfen keine Kommata in den Bemerkungen vorkommen!</p>"\ u"<p>Die Ausgabedatei wird in demselben Verzeichnis erzeugt, wo die Eingabedatei liegt.\ Sie hat den gleichen Namen mit dem Zusatz '_konvertiert'.\ Es öffnet sich nun ein Fenster, wo man die Eingabedatei auswählen kann.</p>"\ u"<p>Sollte etwas nicht funktionieren, frag Boris ;).</p>" reply = QtGui.QMessageBox.information(self, "Achtung!", MESSAGE) if reply == QtGui.QMessageBox.Ok: csv_ein = QtGui.QFileDialog.getOpenFileName(self, u'CSV-Datei öffnen','.') if csv_ein: konvertiere(str(csv_ein))
class FrmArqueo( Ui_frmArqueo, Base ): ''' Esta clase implementa el formulario arqueo ''' web = "arqueos.php?doc=" def __init__( self, datos_sesion, parent, edit = False ): u''' @param datos_sesion: La información de la sesion de caja ''' super( FrmArqueo, self ).__init__( parent, True ) self.sesion = datos_sesion self.setWindowModality( Qt.WindowModal ) self.setWindowFlags( Qt.Dialog ) # self.status = False self.__dolar_proxy = ArqueoProxyModel() self.__cordoba_proxy = ArqueoProxyModel() self.editmodel = None # El modelo principal self.navmodel = QSqlQueryModel( self ) # El modelo que filtra a self.navmodel self.navproxymodel = QSortFilterProxyModel( self ) self.__details_proxymodel_d = QSortFilterProxyModel( self ) self.__details_proxymodel_c = QSortFilterProxyModel( self ) self.navproxymodel.setSourceModel( self.navmodel ) # Este es el modelo con los datos de la tabla con los detalles self.detailsModel = QSqlQueryModel( self ) # Este es el filtro del modelo anterior self.detailsproxymodel = QSortFilterProxyModel( self ) self.detailsproxymodel.setSourceModel( self.detailsModel ) #filtrar en dolares y en cordobas self.__details_proxymodel_d.setSourceModel( self.detailsproxymodel ) self.__details_proxymodel_d.setFilterKeyColumn( MONEDA ) self.__details_proxymodel_d.setFilterRegExp( "^%d$" % constantes.IDDOLARES ) self.__details_proxymodel_c.setSourceModel( self.detailsproxymodel ) self.__details_proxymodel_c.setFilterKeyColumn( MONEDA ) self.__details_proxymodel_c.setFilterRegExp( "^%d$" % constantes.IDCORDOBAS ) if edit: self.status = False self.newDocument() self.actionCancel.setVisible(False) self.tabWidget.setTabEnabled(1,False) else: self.status = True QTimer.singleShot( 0, self.loadModels ) def updateModels( self ): try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( "No se pudo abrir la base de datos" ) #TODO: Esta consulta tiene que mejorar para definir realmente quien es el que realiza el arqueo query = u""" SELECT d.iddocumento, d.fechacreacion , p.nombre AS 'Arqueador', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOEFECTIVO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'efectivoc', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOEFECTIVO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'efectivod', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOCHEQUE ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'chequec', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOCHEQUE ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'chequed', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGODEPOSITO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'depositoc', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGODEPOSITO ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'depositod', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTRANSFERENCIA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'transferenciac', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTRANSFERENCIA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'transferenciad', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTARJETA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDCORDOBAS ) + """, mc.monto, 0)),4) AS 'tarjetac', FORMAT(SUM(IF(mc.idtipomovimiento = """ + str( constantes.IDPAGOTARJETA ) + """ AND mc.idtipomoneda = """ + str( constantes.IDDOLARES ) + """, mc.monto, 0)),4) AS 'tarjetad' FROM documentos d JOIN movimientoscaja mc ON mc.iddocumento = d.iddocumento JOIN tiposmoneda tm ON mc.idtipomoneda = tm.idtipomoneda JOIN personasxdocumento pxd ON pxd.iddocumento = d.iddocumento JOIN personas p ON p.idpersona = pxd.idpersona WHERE d.idtipodoc = %d GROUP BY d.iddocumento """ % ( constantes.IDARQUEO ) self.navmodel.setQuery( query ) self.detailsModel.setQuery( u""" SELECT l.cantidad AS 'Cantidad', CONCAT_WS(' ',tm.simbolo, CAST(de.valor AS CHAR)) as 'Denominación', FORMAT(l.cantidad * de.valor, 4) as 'Total', de.idtipomoneda, l.iddocumento FROM lineasarqueo l JOIN denominaciones de ON de.iddenominacion = l.iddenominacion JOIN tiposmoneda tm ON de.idtipomoneda = tm.idtipomoneda JOIN documentos d ON d.iddocumento = l.iddocumento JOIN tiposcambio tc ON d.idtipocambio = tc.idtc """ ) self.mapper.setSubmitPolicy( QDataWidgetMapper.ManualSubmit ) self.mapper.setModel( self.navproxymodel ) self.mapper.addMapping( self.dtPicker, FECHA ) self.mapper.addMapping( self.lblUserName, NOMBRE, "value" ) self.mapper.addMapping( self.sbCkC, CHEQUEC, "value" ) self.mapper.addMapping( self.sbCkD, CHEQUED, "value" ) self.mapper.addMapping( self.sbCardC, TARJETAC, "value" ) self.mapper.addMapping( self.sbCardD, TARJETAD, "value" ) self.mapper.addMapping( self.sbDepositC, DEPOSITOC, "value" ) self.mapper.addMapping( self.sbDepositD, DEPOSITOD, "value" ) self.mapper.addMapping( self.sbTransferC , TRANSFERENCIAC, "value" ) self.mapper.addMapping( self.sbTransferD , TRANSFERENCIAD, "value" ) except UserWarning as inst: logging.error( unicode( inst ) ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) except Exception as inst: logging.critical( unicode( inst ) ) finally: if self.database.isOpen(): self.database.close() def updateDetailFilter( self, index ): self.detailsproxymodel.setFilterKeyColumn( IDDOCUMMENTOT ) self.detailsproxymodel.setFilterRegExp( self.navmodel.record( index ).value( IDDOCUMMENTO ).toString() ) self.tablenavigation.selectRow( self.mapper.currentIndex() ) def setControls( self, status ): """ @param status: false = editando true = navegando """ self.actionPrint.setVisible( status ) self.tablenavigation.setEnabled( status ) self.tabnavigation.setEnabled( status ) self.actionNew.setVisible( status ) self.actionPreview.setVisible( status ) self.actionCancel.setVisible( not status ) self.actionSave.setVisible( not status ) self.actionGoFirst.setVisible( status ) self.actionGoLast.setVisible( status ) self.actionGoNext.setVisible( status ) self.actionGoPrevious.setVisible( status ) self.sbCkD.setReadOnly( status ) self.sbCkC.setReadOnly( status ) self.sbCardD.setReadOnly( status ) self.sbCardC.setReadOnly( status ) self.sbDepositD.setReadOnly( status ) self.sbDepositC.setReadOnly( status ) self.sbTransferD.setReadOnly( status ) self.sbTransferC.setReadOnly( status ) self.txtObservations.setReadOnly( status ) self.tablenavigation.setColumnHidden( IDDOCUMMENTO, True ) if not self.status: self.tabledetailsC.setEditTriggers( QTableView.AllEditTriggers ) self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, False ) self.tabledetailsD.setEditTriggers( QTableView.AllEditTriggers ) self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, False ) self.tabWidget.setCurrentIndex( 0 ) self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, True ) self.tabledetailsC.setColumnHidden( IDDENOMINACION, True ) self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, True ) self.tabledetailsD.setColumnHidden( IDDENOMINACION, True ) # doublevalidator = QDoubleValidator(0, 99999999, 4, self) else: self.tabledetailsC.setModel( self.__details_proxymodel_c ) self.tabledetailsD.setModel( self.__details_proxymodel_d ) self.tablenavigation.setModel( self.navproxymodel ) self.tablenavigation.setColumnHidden( IDDOCUMMENTO, True ) self.tabledetailsC.setColumnHidden( IDDOCUMMENTOT, True ) self.tabledetailsC.setColumnHidden( IDDENOMINACION, True ) self.tabledetailsD.setColumnHidden( IDDOCUMMENTOT, True ) self.tabledetailsD.setColumnHidden( IDDENOMINACION, True ) self.tabledetailsC.setColumnHidden( MONEDA, True ) self.tabledetailsD.setColumnHidden( MONEDA, True ) def updateLabels( self ): self.lblCashC.setText( "%s / %s" % ( moneyfmt( self.editmodel.totalCashC, 4, "C$" ), moneyfmt( self.editmodel.expectedCashC, 4, "C$" ) ) ) self.lblCashD.setText( "%s / %s" % ( moneyfmt( self.editmodel.totalCashD, 4, "US$" ), moneyfmt( self.editmodel.expectedCashD, 4, "US$" ) ) ) self.lblCkC.setText( moneyfmt( self.editmodel.expectedCkC, 4, "C$" ) ) self.lblCkD.setText( moneyfmt( self.editmodel.expectedCkD, 4, "US$" ) ) self.lblCardC.setText( moneyfmt( self.editmodel.expectedCardC, 4, "C$" ) ) self.lblCardD.setText( moneyfmt( self.editmodel.expectedCardD, 4, "US$" ) ) self.lblDepositC.setText( moneyfmt( self.editmodel.expectedDepositC, 4, "C$" ) ) self.lblDepositD.setText( moneyfmt( self.editmodel.expectedDepositD, 4, "US$" ) ) self.lblTransferC.setText( moneyfmt( self.editmodel.expectedDepositC, 4, "C$" ) ) self.lblTransferD.setText( moneyfmt( self.editmodel.expectedDepositD, 4, "US$" ) ) def newDocument( self ): """ cargar todos los modelos para la edición """ query = QSqlQuery() try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo establecer la conexión con la base de datos" ) for window in self.parentWindow.findChild( QMdiArea ).subWindowList(): if window.widget(): raise UserWarning( u"Por favor cierre las otras pestañas" + u" de la aplicación antes de continuar" + " con el arqueo" ) self.editmodel = ArqueoModel( self.sesion ) self.editmodel.datetime.setDate( self.sesion.fecha ) self.editmodel.datetime.setTime( QTime.currentTime() ) self.__dolar_proxy.setSourceModel( self.editmodel ) self.__dolar_proxy.setFilterKeyColumn( MONEDA ) self.__dolar_proxy.setFilterRegExp( r"^%d$" % constantes.IDDOLARES ) self.__dolar_proxy.setDynamicSortFilter( True ) self.__cordoba_proxy.setSourceModel( self.editmodel ) self.__cordoba_proxy.setFilterKeyColumn( MONEDA ) self.__cordoba_proxy.setFilterRegExp( r"^%d$" % constantes.IDCORDOBAS ) self.__cordoba_proxy.setDynamicSortFilter( True ) self.tabledetailsC.setModel( self.__cordoba_proxy ) self.tabledetailsD.setModel( self.__dolar_proxy ) if not self.database.isOpen(): if not self.database.open(): raise UserWarning( "No se pudo conectar con la base de datos" ) #verificar si hay documentos pendientes de aprobación q = """ SELECT CONCAT_WS(' ', td.descripcion, d.ndocimpreso) FROM documentos sesion JOIN docpadrehijos dpd ON dpd.idpadre = sesion.iddocumento JOIN documentos d ON dpd.idhijo = d.iddocumento JOIN tiposdoc td ON td.idtipodoc = d.idtipodoc WHERE d.idestado NOT IN ( %d,%d) """ % ( constantes.CONFIRMADO, constantes.ANULADO ) if not query.exec_( q ): raise Exception( u"No se pudo ejecutar la consulta para "\ + "determinar si existen documentos " + "pendientes de aprobación" ) if not query.size() == 0: raise UserWarning( u"Existen documentos pendientes de "\ + "aprobación en la sesión" ) #Obtener los datos de la sesión q = """ CALL spConsecutivo( %d, NULL ) """ % constantes.IDARQUEO #query.prepare( q ) if not query.exec_( q ): raise Exception( u"No se pudo ejecutar la consulta para "\ + "obtener el numero del arqueo" ) if not query.size() > 0: raise Exception( u"La consulta para obtener el numero del "\ + "arqueo no devolvio ningún valor" ) query.first() self.editmodel.printedDocumentNumber = query.value( 0 ).toString() self.editmodel.exchangeRateId = self.sesion.tipoCambioId self.editmodel.exchangeRate = self.sesion.tipoCambioOficial self.editmodel.datetime.setDate( self.sesion.fecha ) q = """ CALL spTotalesSesion(%d); """ % self.sesion.sesionId if not query.exec_( q ): raise UserWarning( u"No se pudieron calcular los totales"\ + " de la sesión" ) while query.next(): if query.value( 0 ).toInt()[0] == constantes.IDPAGOEFECTIVO and query.value( 2 ).toInt()[0] == constantes.IDDOLARES: self.editmodel.expectedCashD = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOEFECTIVO and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS: self.editmodel.expectedCashC = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOCHEQUE and query.value( 2 ).toInt()[0] == constantes.IDDOLARES: self.editmodel.expectedCkD = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOCHEQUE and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS: self.editmodel.expectedCkC = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGODEPOSITO and query.value( 2 ).toInt()[0] == constantes.IDDOLARES: self.editmodel.expectedDepositD = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGODEPOSITO and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS: self.editmodel.expectedDepositC = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTRANSFERENCIA and query.value( 2 ).toInt()[0] == constantes.IDDOLARES: self.editmodel.expectedTransferD = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTRANSFERENCIA and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS: self.editmodel.expectedTransferC = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTARJETA and query.value( 2 ).toInt()[0] == constantes.IDDOLARES: self.editmodel.expectedCardD = Decimal( query.value( 5 ).toString() ) elif query.value( 0 ).toInt()[0] == constantes.IDPAGOTARJETA and query.value( 2 ).toInt()[0] == constantes.IDCORDOBAS: self.editmodel.expectedCardC = Decimal( query.value( 5 ).toString() ) q = """ SELECT d.iddenominacion, CONCAT_WS( ' ',d.valor, m.moneda), d.valor, d.idtipomoneda, m.simbolo FROM denominaciones d JOIN tiposmoneda m ON d.idtipomoneda = m.idtipomoneda WHERE d.activo = 1 ORDER BY d.idtipomoneda, d.valor """ if not query.exec_( q ): raise UserWarning( "No se pudo recuperar la lista de " + "denominaciones" ) denominationsmodelC = SingleSelectionModel() denominationsmodelC.headers = ["Id", u"Denominación", "Valor", "Id Moneda", "Simbolo"] denominationsmodelD = SingleSelectionModel() denominationsmodelD.headers = denominationsmodelC.headers while query.next(): if query.value( 3 ).toInt()[0] == constantes.IDDOLARES: denominationsmodelD.items.append( [ query.value( 0 ).toInt()[0], #el id del tipo de denominacion query.value( 1 ).toString(), #La descripción de la denominación query.value( 2 ).toString(), # el valor de la denominación query.value( 3 ).toInt()[0], #El id del tipo de moneda query.value( 4 ).toString() #El simbolo de la moneda ] ) else: denominationsmodelC.items.append( [ query.value( 0 ).toInt()[0], #el id del tipo de denominacion query.value( 1 ).toString(), #La descripción de la denominación query.value( 2 ).toString() , # el valor de la denominación query.value( 3 ).toInt()[0], #El id del tipo de moneda query.value( 4 ).toString() #El simbolo de la moneda ] ) delegateC = ArqueoDelegate( denominationsmodelC ) self.tabledetailsC.setItemDelegate( delegateC ) delegateD = ArqueoDelegate( denominationsmodelD ) self.tabledetailsD.setItemDelegate( delegateD ) self.addLine() self.addLine() self.editmodel.setData( self.editmodel.index( 0, MONEDA ), constantes.IDDOLARES ) self.editmodel.setData( self.editmodel.index( 1, MONEDA ), constantes.IDCORDOBAS ) self.dtPicker.setDateTime( self.editmodel.datetime ) self.lblUserName.setText( self.user.fullname ) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect( self.updateLabels ) self.tabledetailsC.setColumnWidth( DENOMINACION, 200 ) self.tabledetailsD.setColumnWidth( DENOMINACION, 200 ) self.updateLabels() self.status = False except UserWarning as inst: logging.error( unicode( inst ) ) logging.error( query.lastError().text() ) QMessageBox.critical( self, qApp.organizationName(), unicode( inst ) ) self.status = True except Exception as inst: logging.critical( unicode( inst ) ) logging.critical( query.lastError().text() ) QMessageBox.critical( self, qApp.organizationName(), "El sistema no pudo iniciar un nuevo arqueo" ) self.status = True finally: if self.database.isOpen(): self.database.close() @pyqtSlot( QDateTime ) def on_dtPicker_dateTimeChanged( self, datetime ): pass def cancel( self ): self.editmodel = None self.status = True self.navigate( 'last' ) def save( self ): """ Redefiniendo el metodo save de Base para mostrar advertencias si el arqueo no concuerda """ try: errors = [] if not self.editmodel.totalCashC == self.editmodel.expectedCashC: errors.append( u"El total de efectivo en cordobas del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalCashD == self.editmodel.expectedCashD: errors.append( u"El total de efectivo en dolares del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalCkD == self.editmodel.expectedCkD: errors.append( u"El total de cheques en dolares del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalCkC == self.editmodel.expectedCkC: errors.append( u"El total de cheques en cordobas del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalTransferD == self.editmodel.expectedTransferD: errors.append( u"El total de transferencias en dolares del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalTransferC == self.editmodel.expectedTransferC: errors.append( u"El total de transferencias en cordobas del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalDepositD == self.editmodel.expectedDepositD: errors.append( u"El total de depositos en dolares del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalDepositC == self.editmodel.expectedDepositC: errors.append( u"El total de depositos en cordobas del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalCardD == self.editmodel.expectedDepositD: errors.append( u"El total de pagos en tarjetas en dolares del arqueo no coincide con el de la sesión" ) if not self.editmodel.totalCardD == self.editmodel.expectedDepositC: errors.append( u"El total de pagos en tarjetas en cordobas del arqueo no coincide con el de la sesión" ) if len( errors ) > 0: raise UserWarning( "\n".join( errors ) ) dlgUser = dlgSmallUserLogin() if dlgUser.exec_() == QDialog.Accepted: if dlgUser.user.valid and dlgUser.user.hasRole( 'gerencia' ): self.editmodel.authorizationId = dlgUser.user.uid super( FrmArqueo, self ).save( False ) self.parentWindow.init() self.close() else: QMessageBox.warning( self, qApp.organizationName(), "No se pudo autorizar el arqueo" ) except UserWarning as inst: if not self.editmodel.observations == "": if QMessageBox.question( self, qApp.organizationName(), unicode( inst ) + u"\n¿Desea Continuar?", QMessageBox.Yes | QMessageBox.No ) == QMessageBox.Yes: dlgUser = dlgSmallUserLogin() if dlgUser.exec_() == QDialog.Accepted: if dlgUser.user.valid and dlgUser.user.hasRole( 'gerencia' ): self.editmodel.authorizationId = dlgUser.user.uid super( FrmArqueo, self ).save( False ) self.parentWindow.init() self.close() else: QMessageBox.warning( self, qApp.organizationName(), "No se pudo autorizar " + "el arqueo" ) else: QMessageBox.warning( self, qApp.organizationName(), unicode( inst )\ + u"\n Por favor especifique el motivo" + " de la diferencia" ) @property def printIdentifier( self ): return self.navmodel.record( self.mapper.currentIndex() ).value( "iddocumento" ).toString() def navigate( self, to ): """ Esta funcion se encarga de navegar entro los distintos documentos @param to: es una string que puede tomar los valores 'next' 'previous' 'first' 'last' """ if self.mapper.currentIndex != -1: row = self.mapper.currentIndex() if to == "next": row += 1 if row >= self.navproxymodel.rowCount(): row = self.navproxymodel.rowCount() - 1 self.mapper.setCurrentIndex( row ) elif to == "previous": if row <= 1: row = 0 else: row = row - 1 self.mapper.setCurrentIndex( row ) elif to == "first": self.mapper.toFirst() elif to == "last": self.mapper.toLast() else: self.mapper.toLast()() self.tabledetailsC.resizeColumnsToContents() self.tabledetailsC.horizontalHeader().setStretchLastSection( True ) self.tabledetailsD.resizeColumnsToContents() self.tabledetailsD.horizontalHeader().setStretchLastSection( True ) self.tablenavigation.selectRow( self.mapper.currentIndex() ) @pyqtSlot( float ) @if_edit_model def on_sbCkD_valueChanged( self, value ): self.editmodel.totalCkD = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbCkC_valueChanged( self, value ): self.editmodel.totalCkC = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbCardD_valueChanged( self, value ): self.editmodel.totalCardD = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbCardC_valueChanged( self, value ): self.editmodel.totalCardC = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbDepositD_valueChanged( self, value ): self.editmodel.totalDepositD = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbDepositC_valueChanged( self, value ): self.editmodel.totalDepositC = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbTransferD_valueChanged( self, value ): self.editmodel.totalTransferD = Decimal( str( value ) ) @pyqtSlot( float ) @if_edit_model def on_sbTransferC_valueChanged( self, value ): self.editmodel.totalTransferC = Decimal( str( value ) )
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 tbFactura(QTabWidget, Ui_tbFactura): """ Implementacion de la interfaz grafica para facturas """ web = "facturas.php?doc=" DATE_FORMAT = "dd/MM/yyyy" def __init__(self): ''' Constructor ''' super(tbFactura, self).__init__() # ESTABLECER LA INTERFAZ AL FORMULARIO self.setupUi(self) # VALIDADOR DE MODO DE EDICION self.readOnly = True self.editmodel = None #ESTABLECER LA FECHA INICIAL , (establecida al dia de mañana) self.categoriesview.headers = [ "Descripcion", "Precio", "Unidades", "Existencia", "", "", "" ] # Crear el modelo para cargar catalogo de clientes self.clientesModel = QSqlQueryModel() # Crear lista de autocompletado para el combo de clientes self.clienteCompleter = QCompleter() # Modelo que carga el catalogo de productos self.existenciaModel = QSqlQueryModel() # Establecer todos los controles en modo de edicion self.setControls(False) # Crear la conexion a la base de datos self.database = QSqlDatabase.database() self.vistaprevia = False # Cargar los modelos del modo de edicion self.updateEditModels() self.parent = self.parent() def newDocument(self): """ activar todos los controles, llenar los modelos necesarios, crear el modelo FacturaModel, aniadir una linea a la tabla """ self.readOnly = False if not self.updateEditModels(): return self.status = False self.dtPicker.setDate(self.parentWindow.datosSesion.fecha) def updateEditModels(self): """ Este metodo actualiza los modelos usados en el modo edición """ resultado = False try: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo abrir la conexión "\ + "con la base de datos" ) self.clientesModel.setQuery(""" SELECT idpersona , nombre AS cliente FROM personas WHERE escliente = 1 """) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setModelColumn(1) self.clienteCompleter.setCaseSensitivity(Qt.CaseInsensitive) self.clienteCompleter.setModel(self.clientesModel) self.clienteCompleter.setCompletionColumn(1) self.cbcliente.setCompleter(self.clienteCompleter) self.editmodel = FacturaModel() # Cargar el numero de la factura actual query = QSqlQuery(""" SELECT MAX(CAST( IFNULL(referencia,0) AS SIGNED)) FROM documentos d WHERE idtipodoc =%d; """ % constantes.IDFACTURA) if not query.exec_(): raise Exception("No se pudo obtener el numero de la factura") query.first() if query.size() == 0: n = 1 else: n = str(int(query.value(0)) + 1) self.editmodel.printedDocumentNumber = str( int(query.value(0)) + 1) self.lblnumero.setText(n) # if self.clientesModel.rowCount() == 0: # raise UserWarning( "No existen clientes en la"\ # + " base de datos" ) # return self.clienteCompleter.setModel(self.clientesModel) self.cbcliente.setModel(self.clientesModel) self.cbcliente.setCompleter(self.clienteCompleter) # #Crear el delegado con los articulo y verificar si existen articulos self.existenciaModel.setQuery( QSqlQuery(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos -- WHERE existencia >0 """)) self.categoriesview.update(""" SELECT categoria, descripcion, precio, unidadesxcaja, -- cajas, 100 as cajas, idprecioproducto FROM vw_articulos WHERE idprecioproducto IS NOT NULL -- WHERE existencia >0 """) self.categoriesview.expandAll() self.categoriesview.setColumnHidden(3, True) self.categoriesview.setColumnHidden(4, True) self.categoriesview.setColumnWidth(0, 150) self.categoriesview.setColumnWidth(1, 60) self.categoriesview.setColumnWidth(2, 20) self.proxyexistenciaModel = SingleSelectionModel() self.proxyexistenciaModel.setSourceModel(self.existenciaModel) # self.proxyexistenciaModel.setFilterKeyColumn( IDBODEGAEX ) if self.proxyexistenciaModel.rowCount() == 0: raise UserWarning("No hay articulos en bodega") delegate = FacturaDelegate(self.proxyexistenciaModel) self.tabledetails.setItemDelegate(delegate) self.tabledetails.setModel(self.editmodel) self.tabledetails.setColumnHidden(0, True) # self.editmodel.insertRow(1) self.editmodel.dataChanged[QModelIndex, QModelIndex].connect(self.updateLabels) self.txtobservaciones.setPlainText("") self.dtPicker.setDate(QDate.currentDate().addDays(1)) self.editmodel.fecha = QDate.currentDate().addDays(1) self.cbcliente.setCurrentIndex(-1) resultado = True except UserWarning as inst: logging.error(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), unicode(inst)) finally: if self.database.isOpen(): self.database.close() return resultado def addActionsToToolBar(self): self.actionRefresh = self.createAction( text="Actualizar", icon=QIcon.fromTheme('view-refresh', QIcon(":/icons/res/view-refresh.png")), slot=self.refresh, shortcut=Qt.Key_F5) self.toolBar.addActions([ self.actionNew, self.actionRefresh, self.actionPreview, self.actionPrint, self.actionSave, self.actionCancel, ]) self.toolBar.addSeparator() self.toolBar.addActions([ self.actionGoFirst, self.actionGoPrevious, self.actionGoLast, self.actionGoNext, self.actionGoLast ]) def refresh(self): """ Actualizar los modelos de edición """ if not self.status: if QMessageBox.question( self, qApp.organizationName(), u"Se perderán todos los cambios en la factura. ¿Esta seguro que desea actualizar?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.No: return self.updateEditModels() else: if self.updateModels(): QMessageBox.information( None, "Factura", u"Los datos fueron actualizados con éxito") def printDocument1(self): html = u"" date = QDate.currentDate().toString(self.DATE_FORMAT) address = Qt.escape("Bario francisco mesa").replace(",", "<br>") contact = Qt.escape("Luis Mejia") balance = 5000 html += ("<p align=right><img src=':/logo.png'></p>" "<p> align = right>Greasy hands ltd." "<br>New Lombard Street" "<br>London<br>WC13 4PX<br>%s</p>" "<p>%s</p><p>Dear %s, </p>" "<p>The balance of your account is %s.") % ( date, address, contact, QString("$ %L1").arg( float(balance), 0, "f", 2)) if balance < 0: html += ( "<p><font color =red><b> Please remit the amount owing immediately.</b></font>" ) else: html += "We are delighted to have done business with you." html += ( "</p><p> </p><p>" "<table border=1 cellpadding=2 cellspacing=2><tr><td colspan=3>Transaction</td></tr>" ) transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500), (QDate.currentDate(), -500), (QDate.currentDate(), 500)] for date, amount in transactions: color, status = "black", "Credit" if amount < 0: color, status = "red", "Debid" html += ( "<tr>" "<td align= right>%s</td>" "<td>%s</td><td align=right><font color=%s>%s</font></td></tr>" % (date.toString(self.DATE_FORMAT), status, color, QString("$ %L1").arg(float(abs(amount)), 0, "f", 2))) html += ("</table></p><p style='page-break-after=always;'>" "We hope to continue doing business with you</p>") pdialog = QPrintDialog() if pdialog.exec_() == QDialog.Accepted: printer = pdialog.printer() document = QTextDocument() document.setHtml(html) document.print_(printer) def printDocument2(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() headFormat = QTextBlockFormat() headFormat.setAlignment(Qt.AlignLeft) headFormat.setTextIndent(self.printer.pageRect().width() - 216) bodyFormat = QTextBlockFormat() bodyFormat.setAlignment(Qt.AlignJustify) lastParaBodyFormat = QTextBlockFormat(bodyFormat) lastParaBodyFormat.setPageBreakPolicy( QTextFormat.PageBreak_AlwaysAfter) rightBodyFormat = QTextBlockFormat() rightBodyFormat.setAlignment(Qt.AlignRight) headCharFormat = QTextCharFormat() headCharFormat.setFont(QFont("Helvetica", 10)) bodyCharFormat = QTextCharFormat() bodyCharFormat.setFont(QFont("Times", 11)) redBodyCharFormat = QTextCharFormat(bodyCharFormat) redBodyCharFormat.setForeground(Qt.red) tableFormat = QTextTableFormat() tableFormat.setBorder(1) tableFormat.setCellPadding(2) document = QTextDocument() cursor = QTextCursor(document) mainFrame = cursor.currentFrame() page = 1 cursor.insertBlock(headFormat, headCharFormat) for text in ("Greasy Hands Ltd.", "New Lombard Street", "London", "WC13", QDate.currentDate().toString(self.DATE_FORMAT)): cursor.insertBlock(headFormat, headCharFormat) cursor.insertText(text) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Barrio Francisco Meza") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Dear Lyuis") cursor.insertBlock(bodyFormat) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText( QString("The balance of your account is $ %L1.").arg( float(500.987), 0, "f", 2)) cursor.insertBlock(bodyFormat, redBodyCharFormat) cursor.insertText("Please remit the amount") cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("Transaction") transactions = [(QDate.currentDate(), 500), (QDate.currentDate(), 500), (QDate.currentDate(), -500), (QDate.currentDate(), 500)] table = cursor.insertTable(len(transactions), 3, tableFormat) row = 0 for date, amount in transactions: cellCursor = table.cellAt(row, 0).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText(date.toString(self.DATE_FORMAT), bodyCharFormat) cellCursor = table.cellAt(row, 1).firstCursorPosition() cellCursor.insertText("Credit", bodyCharFormat) cellCursor = table.cellAt(row, 2).firstCursorPosition() cellCursor.setBlockFormat(rightBodyFormat) cellCursor.insertText( QString("The balance of your account is $ %L1.").arg( float(amount), 0, "f", 2), redBodyCharFormat) row += 1 cursor.setPosition(mainFrame.lastPosition()) cursor.insertBlock(bodyFormat, bodyCharFormat) cursor.insertText("We hope") document.print_(self.printer) def printDocument(self): dialog = QPrintDialog() if not dialog.exec_(): return self.printer = dialog.printer() self.imprimir(self.printer) self.document.load(self.editmodel) def preview(self): self.vistaprevia = True preview = frmImpresion(self) preview.exec_() def save(self): """ Guardar el documento actual @rtype: bool """ result = False try: if not self.valid: return False if QMessageBox.question( self, qApp.organizationName(), u"¿Esta seguro que desea guardar la factura?", QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes: if not self.database.isOpen(): if not self.database.open(): raise UserWarning( u"No se pudo conectar con la base de datos") self.editmodel.observaciones = self.txtobservaciones.toPlainText( ) if not self.editmodel.save(): raise UserWarning("No se ha podido guardar la factura") QMessageBox.information( None, qApp.organizationName(), u"""El documento se ha guardado con éxito""") self.readOnly = True self.updateModels() # self.navigate( 'last' ) # self.status = True result = True except UserWarning as inst: logging.error(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), unicode(inst)) except Exception as inst: logging.critical(unicode(inst)) QMessageBox.critical(self, qApp.organizationName(), u"Hubo un error al guardar la factura") finally: if self.database.isOpen(): self.database.close() return result # @pyqtSlot(QModelIndex) # def on_categoriesview_doubleClicked(self,index): @pyqtSlot(QModelIndex) def on_categoriesview_activated(self, index): articulo = self.categoriesview.model().asRecord(index) if len(articulo) > 0: nuevo = True for i, line in enumerate(self.editmodel.lines): if line.itemId == articulo[5]: nuevo = False fila = i line = self.editmodel.lines[self.editmodel.rowCount() - 1] if nuevo: fila = self.editmodel.rowCount() self.editmodel.insertRow(fila) self.parent.saveAct.setEnabled(True) linea = self.editmodel.lines[fila] linea.itemDescription = articulo[0] + " " + articulo[1] linea.itemPrice = Decimal(articulo[2]) linea.itemId = articulo[5] linea.quantityperbox = int(articulo[3]) self.editmodel.lines[fila].quantity += 1 self.editmodel.lines[fila].existencia = int( articulo[4]) - self.editmodel.lines[fila].quantity indice = self.editmodel.index(fila, 2) self.editmodel.dataChanged.emit(indice, indice) indice = self.editmodel.index(fila, 3) self.editmodel.dataChanged.emit(indice, indice) indice = self.editmodel.index(fila, 5) self.editmodel.dataChanged.emit(indice, indice) @pyqtSlot() def on_btneditar_clicked(self): articulo = dlgArticulo(self) articulo.exec_() self.updateEditModels() @pyqtSlot(int) def on_cbcliente_currentIndexChanged(self, index): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: numero = self.clientesModel.record(index).value("idpersona") self.editmodel.clienteId = int(numero) if numero is not None else 0 @pyqtSlot(unicode) def on_cbcliente_editTextChanged(self, text): """ asignar proveedor al objeto self.editmodel """ if self.editmodel is not None: self.editmodel.cliente = str(text) @pyqtSlot(int) def on_cbvendedor_currentIndexChanged(self, index): """ asignar proveedor al objeto self.editmodel """ self.editmodel.vendedorId = self.vendedoresModel.record(index).value( "idpersona").toInt()[0] @pyqtSlot(QDate) def on_dtPicker_dateChanged(self, date): if self.editmodel is not None: self.editmodel.fecha = date @pyqtSlot(bool) def on_rbcontado_toggled(self, on): """ Asignar las observaciones al objeto editmodel """ self.editmodel.escontado = 1 if on else 0 def on_txtSearch_textChanged(self, text): """ Cambiar el filtro de busqueda """ self.filtermodel.setFilterRegExp(text) def setControls(self, status): """ @param status: false = editando true = navegando """ # self.actionPrint.setVisible( status ) self.readOnly = status self.txtobservaciones.setReadOnly(status) # self.actionPreview.setVisible( status ) # self.actionAnular.setVisible( status ) # self.toolBar.setVisible(status) # self.lblnfac.setText( self.editmodel.printedDocumentNumber ) self.swcliente.setCurrentIndex(0) self.lbltotal.setText("C$ 0.00") self.tabledetails.setEditTriggers(QAbstractItemView.AllEditTriggers) # self.lblanulado.setHidden( True ) self.tabledetails.horizontalHeader().setStretchLastSection(True) self.tabledetails.setColumnHidden(IDARTICULO, True) self.tabledetails.setColumnHidden(IDDOCUMENTOT, True) def updateLabels(self): self.lbltotal.setText(moneyfmt(self.editmodel.total, 2, "C$ ")) @property def valid(self): """ Un documento es valido cuando self.printedDocumentNumber != "" self.providerId !=0 self.validLines >0 self.ivaId !=0 self.uid != 0 self.warehouseId != 0 """ if int(self.editmodel.clienteId) == 0 and self.editmodel.cliente == "": QMessageBox.warning(self, qApp.organizationName(), "Por favor elija el cliente") self.cbcliente.setFocus() elif self.editmodel.rowCount() == 0: QMessageBox.warning( self, qApp.organizationName(), "Por favor agregue algun articulo a la factura") else: return True return False def imprimir(self, printer): leftMargin = 72 widthCol = 100 arialFont = QFont("Helvetica", 16, 3) fuente = QFontMetrics(arialFont) arialLineHeight = fuente.height() fondo = QPixmap(":/images/res/fondo.png") painter = QPainter(printer) pageRect = printer.pageRect() page = 1 painter.save() if self.vistaprevia: painter.drawPixmap(0, 0, 530, 830, fondo) painter.setFont(arialFont) y = 180 x = 35 painter.drawText(x, y, self.editmodel.fecha.toString("dd MM yy")) y = 210 x = 85 painter.drawText(x, y, self.editmodel.cliente) painter.setFont(arialFont) cajasFont = QFont("Helvetica", 10, 2) x = -5 y = 295 painter.setFont(cajasFont) painter.drawText(x, y - arialLineHeight - 1, "Cajas") for row in self.editmodel.lines: painter.setFont(cajasFont) x = 2 painter.drawText(x, y, row.cantidad()) painter.setFont(arialFont) total = moneyfmt(row.total, 2, "") x = 470 - fuente.width(total) painter.drawText(x, y, total) x = 310 painter.drawText(x, y, moneyfmt(row.itemPrice, 2, "")) x = 30 painter.drawText(x, y, row.unidades()) x = 80 painter.drawText(x, y, row.itemDescription) y += arialLineHeight total = moneyfmt(self.editmodel.total, 2, "") y = 690 x = 470 - fuente.width(total) painter.drawText(x, y, total) painter.setPen(Qt.black) # printer.newPage() painter.restore()