def __init__(self, mainwindow): QtWidgets.QWidget.__init__(self) self.mainwindow = mainwindow try: self.ui = uic.loadUi('ressource/ui/widget_abfuellung.ui', self) except: print('Kann UI-Datei nicht laden!') sys.exit(1) self.speicher = Speicher() self.pl = Preisliste() self.rabattStufen = [i[1] for i in self.pl.rabattStufen('5er')] while self.ui.combo_manuelleLiter.count() > 0: self.ui.combo_manuelleLiter.removeItem(0) for liter in self.rabattStufen: self.ui.combo_manuelleLiter.addItem('%s' % liter) self.connectSlots() self.stylesheetInputHighlighted = 'background-color: #faa; font-style: italic; border: 1px solid black;' self.stylesheetInputRegular = 'border: 1px solid black; background-color: white;' #for widget in self.ui.stackedWidget.findChildren(QtWidgets.QToolButton): # widget.setStyleSheet('border: 1px solid black;\nbackground-color: white;') self.ui.stackedWidget.widget(0).setStyleSheet( 'background-color: #96ff96;') self.ui.stackedWidget.widget(1).setStyleSheet( 'background-color: #ffffff;') self.ui.stackedWidget.widget(2).setStyleSheet( 'background-color: #9696ff;') self.ui.stackedWidget.widget(3).setStyleSheet( 'background-color: #ff9696;') self.alte_kundenvorgaenge = None self.liter_alte_abfuellungen = 0 self.rabattstufe_berechnen = True self.modus = 'speichern' self.neuerVorgang()
def html_tagesstatistik(year = None): stat = tagesstatistik(year) html = '' tage = sorted(list(stat.keys())) tage.reverse() pl = Preisliste() for datum in tage: html += '<h3>%s</h3>\n<table>' % datum html += '<tr><td>Liter</td><td>%s</td></tr>\n' % (stat[datum]['liter']) keys = sorted(list(stat[datum].keys())) keys.remove('liter') for key in keys: value = stat[datum][key] desc = pl.getBeschreibung(key) if desc: key = desc + ' (' + key + ')' html += u'<tr><td>%s</td><td>%s</td><td>%.2f €</td></tr>\n' % (key, value[0], value[1]) html += '</table>\n\n' return html
def ueberschuss_nach_preiskategorien(year = None): p = Preisliste() basis_5er = p.getPreis('5er', amount=10000) basis_10er = p.getPreis('10er', amount=10000) rabattstufen = p.rabattStufen('5er') ret = {} speicher = Speicher(year) speicher.backend.db.execute('SELECT liter, manuelle_liter, preislisten_id, anzahl, einzelpreis FROM posten INNER JOIN vorgang ON (posten.vorgang=vorgang.id) WHERE vorgang.currentversion=1') data = speicher.backend.db.fetchall() for line in data: kategorie = 0 if line['manuelle_liter']: kategorie = line['manuelle_liter'] else: for stufe in rabattstufen: if stufe[1] < line['liter']: kategorie = stufe[1] if kategorie not in ret.keys(): ret[kategorie] = 0.0 if line['preislisten_id'] == '5er': ret[kategorie] += line['anzahl'] * (line['einzelpreis'] - basis_5er) if line['preislisten_id'] == '10er': ret[kategorie] += line['anzahl'] * (line['einzelpreis'] - basis_10er) return ret
def __init__(self, invoiceEntry): # Konstruktor der Superklasse aufrufen QtWidgets.QDialog.__init__(self, flags=QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) try: self.ui = uic.loadUi('ressource/ui/invoiceentry.ui', self) except: print('Kann UI-Datei nicht laden!') sys.exit(1) self.showFullScreen() self.__preisliste = Preisliste() # Kopie für "Abbrechen" self.__backup = invoiceEntry.copy() self.__backup_preislistenbezug = (invoiceEntry.preislistenID, invoiceEntry.preisliste_link) self.__default = None if invoiceEntry.preislistenID: self.__default = invoiceEntry.copy() self.invoiceEntry = invoiceEntry self.updateComboProdukt() self.updateOldValues() self.updateDefaultValues() self.update() if not self.invoiceEntry.preislistenID: self.ui.combo_produkt.setCurrentIndex(0) self.ui.input_anzahl.clicked = self.showNumberDialog self.ui.input_einheit.clicked = self.showEinheitDialog self.ui.input_beschreibung.clicked = self.showBeschreibungDialog self.ui.input_einzelpreis.clicked = self.showValueDialog self.ui.input_anzahl.installEventFilter(self) self.ui.input_einheit.installEventFilter(self) self.ui.input_beschreibung.installEventFilter(self) self.ui.input_einzelpreis.installEventFilter(self) self.ui.button_ok.clicked.connect(self.okPressed) self.ui.button_abbrechen.clicked.connect(self.cancelPressed) self.ui.input_anzahl.editingFinished.connect( self.anzahlEditingFinished) self.ui.input_einheit.editingFinished.connect( self.einheitEditingFinished) self.ui.input_beschreibung.editingFinished.connect( self.beschreibungEditingFinished) self.ui.input_einzelpreis.editingFinished.connect( self.einzelpreisEditingFinished) self.ui.combo_steuersatz.currentIndexChanged.connect( self.comboSteuersatzChanged) self.ui.combo_produkt.currentIndexChanged.connect( self.comboProduktChanged) self.ui.combo_rabattstufe.currentIndexChanged.connect( self.comboRabattstufeChanged) self.ui.button_einheit_default.clicked.connect( self.buttonEinheitDefaultClicked) self.ui.button_beschreibung_default.clicked.connect( self.buttonBeschreibungDefaultClicked) self.ui.button_einzelpreis_default.clicked.connect( self.buttonEinzelpreisDefaultClicked) self.ui.button_steuersatz_default.clicked.connect( self.buttonSteuersatzDefaultClicked) self.ui.dateedit_leistungsdatum.dateChanged.connect(self.dateChanged)
class InvoiceEntryDialog(QtWidgets.QDialog): def __init__(self, invoiceEntry): # Konstruktor der Superklasse aufrufen QtWidgets.QDialog.__init__(self, flags=QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint) try: self.ui = uic.loadUi('ressource/ui/invoiceentry.ui', self) except: print('Kann UI-Datei nicht laden!') sys.exit(1) self.showFullScreen() self.__preisliste = Preisliste() # Kopie für "Abbrechen" self.__backup = invoiceEntry.copy() self.__backup_preislistenbezug = (invoiceEntry.preislistenID, invoiceEntry.preisliste_link) self.__default = None if invoiceEntry.preislistenID: self.__default = invoiceEntry.copy() self.invoiceEntry = invoiceEntry self.updateComboProdukt() self.updateOldValues() self.updateDefaultValues() self.update() if not self.invoiceEntry.preislistenID: self.ui.combo_produkt.setCurrentIndex(0) self.ui.input_anzahl.clicked = self.showNumberDialog self.ui.input_einheit.clicked = self.showEinheitDialog self.ui.input_beschreibung.clicked = self.showBeschreibungDialog self.ui.input_einzelpreis.clicked = self.showValueDialog self.ui.input_anzahl.installEventFilter(self) self.ui.input_einheit.installEventFilter(self) self.ui.input_beschreibung.installEventFilter(self) self.ui.input_einzelpreis.installEventFilter(self) self.ui.button_ok.clicked.connect(self.okPressed) self.ui.button_abbrechen.clicked.connect(self.cancelPressed) self.ui.input_anzahl.editingFinished.connect( self.anzahlEditingFinished) self.ui.input_einheit.editingFinished.connect( self.einheitEditingFinished) self.ui.input_beschreibung.editingFinished.connect( self.beschreibungEditingFinished) self.ui.input_einzelpreis.editingFinished.connect( self.einzelpreisEditingFinished) self.ui.combo_steuersatz.currentIndexChanged.connect( self.comboSteuersatzChanged) self.ui.combo_produkt.currentIndexChanged.connect( self.comboProduktChanged) self.ui.combo_rabattstufe.currentIndexChanged.connect( self.comboRabattstufeChanged) self.ui.button_einheit_default.clicked.connect( self.buttonEinheitDefaultClicked) self.ui.button_beschreibung_default.clicked.connect( self.buttonBeschreibungDefaultClicked) self.ui.button_einzelpreis_default.clicked.connect( self.buttonEinzelpreisDefaultClicked) self.ui.button_steuersatz_default.clicked.connect( self.buttonSteuersatzDefaultClicked) self.ui.dateedit_leistungsdatum.dateChanged.connect(self.dateChanged) def okPressed(self): alterPreis = self.__backup.getPreis() neuerPreis = self.invoiceEntry.getPreis() if alterPreis * neuerPreis < 0: # Minus mal Minus gibt Plus, wenn es also < 0 ist, hat sich das vorzeichen geändert. if (QtWidgets.QMessageBox.No == QtWidgets.QMessageBox.warning( self, u'Möglicher Fehler', u'Das Vorzeichen des Einzelpreises hat sich geändert!\nIst das korrekt?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No)): self.invoiceEntry.setPreis(-1 * neuerPreis) self.update() return None if self.__backup.getDatum() != self.invoiceEntry.getDatum(): if (QtWidgets.QMessageBox.No == QtWidgets.QMessageBox.warning( self, u'Möglicher Fehler', u'Das Leistungsdatum dieses Eintrags wurde verändert!\nIst das korrekt?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No)): self.invoiceEntry.setDatum(self.__backup.getDatum()) d = self.__backup.getDatum() if not d: d = datetime.date.today() self.ui.dateedit_leistungsdatum.setDate( QtCore.QDate(d.year, d.month, d.day)) return None self.__backup.unregister() if self.__default: self.__default.unregister() self.close() def cancelPressed(self): self.invoiceEntry.importValues(self.__backup) self.invoiceEntry.setPreislistenID(self.__backup_preislistenbezug[0], self.__backup_preislistenbezug[1]) self.__backup.unregister() if self.__default: self.__default.unregister() self.close() def buttonEinheitDefaultClicked(self): if not self.__default: return self.invoiceEntry.setEinheit(self.ui.label_einheit_default.text()) self.update() def buttonBeschreibungDefaultClicked(self): if not self.__default: return self.invoiceEntry.setPreislistenID(self.__default.preislistenID, self.invoiceEntry.preisliste_link) self.invoiceEntry.setBeschreibung( self.ui.label_beschreibung_default.text()) self.update() def buttonEinzelpreisDefaultClicked(self): if not self.__default: return self.invoiceEntry.setRabattstufe(self.__default.getRabattstufe()) self.invoiceEntry.setPreis(self.__default.getPreis()) self.update() def buttonSteuersatzDefaultClicked(self): if not self.__default: return self.ui.combo_steuersatz.setCurrentIndex( self.ui.combo_steuersatz.findText( self.ui.label_steuersatz_default.text())) def anzahlEditingFinished(self): self.invoiceEntry.setStueckzahl(int(self.ui.input_anzahl.text())) self.comboRabattstufeChanged() self.update() def einheitEditingFinished(self): self.invoiceEntry.setEinheit(str(self.ui.input_einheit.text())) self.update() def beschreibungEditingFinished(self): self.invoiceEntry.setBeschreibung( str(self.ui.input_beschreibung.text())) self.update() def einzelpreisEditingFinished(self): betrag = self.ui.input_einzelpreis.text() betrag = betrag.replace(u' €', '') betrag = betrag.replace(',', '.') self.invoiceEntry.setPreis(float(betrag)) self.update() def comboSteuersatzChanged(self): text = self.ui.combo_steuersatz.currentText() (value, percent) = text.split(' ', 1) try: value = float(value) except: value = 0.0 self.ui.combo_steuersatz.setCurrentIndex(0) self.invoiceEntry.setSteuersatz(value) self.update() def showNumberDialog(self): showNumberInputDialog(self.invoiceEntry) self.comboRabattstufeChanged() self.update() def showEinheitDialog(self): self.invoiceEntry.setEinheit( showTextInputDialog('Einheit', ['Stk', 'Liter', 'Ztr', 'Psch'], self.invoiceEntry.getEinheit())) self.update() def showBeschreibungDialog(self): self.invoiceEntry.setBeschreibung( showTextInputDialog('Beschreibung', [], self.invoiceEntry.getBeschreibung())) self.update() def showValueDialog(self): showValueInputDialog(self.invoiceEntry) self.update() def setzePreiskategorie(self, nonsense=None): self.invoiceEntry.setPreislistenID( self.preislisteIDfuerBeschreibung( self.ui.combo_produkt.currentText()), True) self.update() def preislisteIDfuerBeschreibung(self, beschr): for (key, val) in self.preislistenEintraege.items(): if str(val) == str(beschr): return key return None def preislisteBeschreibungfuerID(self, ID): for (key, val) in self.preislistenEintraege.items(): if key == ID: return val return None def comboProduktChanged(self, newIndex): self.updateDefaultValues() self.update() def comboRabattstufeChanged(self, newIndex=None): if self.__default: rabatte = self.__default.listRabattStufen() self.__default.setStueckzahl(self.invoiceEntry.getStueckzahl()) if newIndex is not None: self.__default.setRabattstufe(rabatte.keys()[newIndex]) if self.__default.getAutomatischeRabattstufe( ) == self.__default.getRabattstufe(): self.__default.setRabattstufe(None) try: cur = list(rabatte.keys()).index( self.__default.getRabattstufe()) self.ui.combo_rabattstufe.blockSignals(True) self.ui.combo_rabattstufe.setCurrentIndex(cur) except ValueError: # Wenn es keine Rabatt-Stufen gibt, dann halt nicht pass finally: self.ui.combo_rabattstufe.blockSignals(False) self.update() def dateChanged(self, qdate): self.invoiceEntry.setDatum( datetime.date(qdate.year(), qdate.month(), qdate.day())) def updateDefaultValues(self): if self.ui.combo_produkt.currentIndex() < 2: if self.__default: self.__default.unregister() self.__default = None else: if not self.__default: self.__default = self.invoiceEntry.copy() self.__default.setPreislistenID( self.preislisteIDfuerBeschreibung( self.ui.combo_produkt.currentText()), False) self.__default.setStueckzahl(self.invoiceEntry.getStueckzahl()) self.__default.setEinheit( self.__default.preislistenWert('einheit')) self.__default.setBeschreibung( self.__default.preislistenWert('beschreibung')) self.__default.setPreis( self.__default.preislistenWert('einzelpreis')) self.__default.setSteuersatz( self.__default.preislistenWert('steuersatz')) def updateOldValues(self): self.ui.label_anzahl_alt.setText( renderIntOrFloat(self.__backup.getStueckzahl())) self.ui.label_einheit_alt.setText(str(self.__backup.getEinheit())) self.ui.label_beschreibung_alt.setText( str(self.__backup.getBeschreibung())) self.ui.label_einzelpreis_alt.setText( getMoneyValue(self.__backup.getPreis())) self.ui.label_steuersatz_alt.setText(u'%.1f %%' % self.__backup.getSteuersatz()) self.ui.label_gesamtpreis_alt.setText( getMoneyValue(self.__backup.getSumme())) d = self.__backup.getDatum() if not d: d = datetime.date.today() self.ui.dateedit_leistungsdatum.setDate( QtCore.QDate(d.year, d.month, d.day)) def updateComboProdukt(self): self.ui.combo_produkt.blockSignals(True) self.ui.combo_rabattstufe.blockSignals(True) self.preislistenEintraege = self.__preisliste.getBeschreibungen() self.ui.combo_produkt.clear() beschreibungen = sorted(list(self.preislistenEintraege.values())) beschreibungen = [ 'Kein Produkt aus der Preisliste', '---------------------------------', ] + beschreibungen self.ui.combo_produkt.addItems(beschreibungen) if self.__default: self.ui.combo_produkt.setCurrentIndex( self.ui.combo_produkt.findText( self.preislisteBeschreibungfuerID( self.__default.preislistenID))) rabatte = self.__preisliste.rabattStufen( self.__default.preislistenID) rabattArt = list(rabatte.keys())[0][0] stufenString = u'Ab %i Stück: je %.2f €' if rabattArt == 'liter': stufenString = u'Ab %i Liter: je %.2f €' if len(rabatte) > 1: self.ui.combo_rabattstufe.clear() self.ui.combo_rabattstufe.addItems([ stufenString % (key[1], value) for key, value in rabatte.items() ]) self.ui.combo_rabattstufe.setEnabled(True) index = 0 try: index = list(rabatte.keys()).index( self.__default.getRabattstufe()) except ValueError: index = 0 finally: self.ui.combo_rabattstufe.setCurrentIndex(index) else: self.ui.combo_rabattstufe.clear() self.ui.combo_rabattstufe.setEnabled(False) else: self.ui.combo_rabattstufe.clear() self.ui.combo_rabattstufe.setEnabled(False) self.ui.combo_produkt.blockSignals(False) self.ui.combo_rabattstufe.blockSignals(False) def update(self): self.ui.label_anzahl_alt.setText(u'%i' % self.__backup.getStueckzahl()) self.ui.label_einheit_alt.setText(str(self.__backup.getEinheit())) self.ui.label_beschreibung_alt.setText( str(self.__backup.getBeschreibung())) self.ui.input_anzahl.setText(u'%i' % int(self.invoiceEntry.getStueckzahl())) self.ui.input_einheit.setText(u'%s' % self.invoiceEntry.getEinheit()) self.ui.input_beschreibung.setText(u'%s' % self.invoiceEntry.getBeschreibung()) self.ui.input_einzelpreis.setText( u'%s' % getMoneyValue(self.invoiceEntry.getPreis())) self.ui.label_gesamtpreis.setText( u'%s' % getMoneyValue(self.invoiceEntry.getSumme())) index = self.ui.combo_steuersatz.findText( u'%.1f' % self.invoiceEntry.getSteuersatz(), flags=QtCore.Qt.MatchStartsWith) if index == -1: self.ui.combo_steuersatz.addItem(u'%.1f %%' % self.invoiceEntry.getSteuersatz()) index = self.ui.combo_steuersatz.findText( u'%.1f' % self.invoiceEntry.getSteuersatz(), flags=QtCore.Qt.MatchStartsWith) self.ui.combo_steuersatz.setCurrentIndex(index) if self.__default: self.ui.label_einheit_default.setText(self.__default.getEinheit()) self.ui.label_beschreibung_default.setText( self.__default.getBeschreibung()) self.ui.label_einzelpreis_default.setText( getMoneyValue(self.__default.getPreis())) self.ui.label_steuersatz_default.setText( u'%.1f %%' % self.__default.getSteuersatz()) else: self.ui.label_einheit_default.setText(u'----') self.ui.label_beschreibung_default.setText(u'----') self.ui.label_einzelpreis_default.setText(u'----') self.ui.label_steuersatz_default.setText(u'----') self.updateComboProdukt() def eventFilter(self, qobject, qevent): if qevent.type() == QtCore.QEvent.MouseButtonPress: qobject.clicked() return False
def html_jahresstatistik(year = None): stat = jahresstatistik(year) if len(stat) < 1: return '' # legacy values = {} numbers = {} for key, value in stat.items(): if key == 'liter': values['liter'] = 0 continue values[key] = value[1] for key, value in stat.items(): if key == 'liter': numbers['liter'] = value continue numbers[key] = value[0] stat = numbers for key in ['liter', '5er', '10er', '5er_vk', '10er_vk', '5er_gebraucht', '10er_gebraucht', '5er_abfuellung_vk', '10er_abfuellung_vk']: if key not in stat.keys(): stat[key] = 0 html = u'' # Schöne Anzeige html += u'<p><strong>Liter gesamt:</strong> %i</p>\n' % stat['liter'] anteil_5er = (float(stat['5er']*5) / (stat['5er']*5 + stat['10er']*10)) * 100 anteil_10er = (float(stat['10er']*10) / (stat['5er']*5 + stat['10er']*10)) * 100 html += u'<h4>Materialverbrauch</h4>' html += u'<table border="1">' html += u'<tr><td>Beutel 5l:</td><td>%i</td><td>(%.1f Kartons, %i%%)</td></tr>\n' % (stat['5er'], float(stat['5er'])/ 400, int(anteil_5er)) html += u'<tr><td>Beutel 10l:</td><td>%i</td><td>(%.1f Kartons, %i%%)</td></tr>\n' % (stat['10er'], float(stat['10er'])/400, int(anteil_10er)) karton_5er = stat['5er'] + stat['5er_abfuellung_vk'] - stat['5er_gebraucht'] html += u'<tr><td>Kartons 5l:</td><td>%i</td><td>(%.1f Paletten)</td></tr>\n' % (karton_5er, float(karton_5er)/800) karton_10er = stat['10er'] + stat['10er_abfuellung_vk'] - stat['10er_gebraucht'] html += u'<tr><td>Kartons 10l:</td><td>%i</td><td>(%.1f Paletten)</td></tr>\n' % (karton_10er, float(karton_10er)/400) try: html += u'<tr><td>Karton Rückläufer 5l:</td><td>%i</td><td>(%i%%)</td></tr>\n' % (stat['5er_gebraucht'], int((float(stat['5er_gebraucht'])/(stat['5er'] + stat['5er_vk']))*100)) html += u'<tr><td>Karton Rückläufer 10l:</td><td>%i</td><td>(%i%%)</td></tr>\n' % (stat['10er_gebraucht'], int((float(stat['10er_gebraucht'])/(stat['10er'] + stat['10er_vk']))*100)) except ZeroDivisionError: html += u'<tr><td colspan="3"><em>Zu wenig Daten...</em></td></tr>\n' html += u'</table>' zw_summe = 0 tagesstat = tagesstatistik(year) tage = sorted(list(tagesstat.keys())) html += '<h4>Kumulierte Liter nach Tagen</h4>\n<table>' for tag in tage: zw_summe += tagesstat[tag]['liter'] html += '<tr><td>%s</td><td>%i</td></tr>' % (tag, zw_summe) html += '</table>' tage_anzahl = 0 for t in tage: if 'liter' in tagesstat[t] and tagesstat[t]['liter'] > 0: tage_anzahl += 1 if tage_anzahl == 0: # Wenn keine Umsätze da sind, macht diese Statistik keinen Sinn. # (Führt sonst zu einem DIV0) return html html += u'<h4>Umsatzstatistik</h4>\n' (anzahl, gesamtsumme, anonym_umsatz, rechnungen_summe) = umsatzstatistik(year) html += u'<dl><dt>Anzahl Kunden</dt><dd>%i</dd>\n' \ u'<dt>Anzahl Arbeitstage</dt><dd>%i</dd>\n' \ u'<dt>Umsatz auf Rechnung</dt><dd>%.2f €</dd>\n' \ u'<dt>Gesamtumsatz</dt><dd>%.2f €</dd>\n' \ u'<dt>davon Laufkundschaft</dt><dd>%.2f €</dd>\n' \ u'<dt>Durchschn. Umsatz pro Kunde</dt><dd>%.2f €</dd>' \ u'<dt>Durchschn. Umsatz pro Tag</dt><dd>%.2f €</dd>' \ u'<dt>Durchschn. Liter pro Tag</dt><dd>%i</dd></dl>' \ % (anzahl, tage_anzahl, rechnungen_summe, gesamtsumme + anonym_umsatz, anonym_umsatz, gesamtsumme / anzahl, gesamtsumme / tage_anzahl, stat['liter'] / tage_anzahl) html += u'<h4>Gewinn gegenüber 500-Liter-Preis nach Preiskategorien</h4>\n<dl>\n' kategorien = ueberschuss_nach_preiskategorien(year) stufen = sorted(list(kategorien.keys())) for key in stufen: value = kategorien[key ] html += u'<dt>%s</dt><dd>%s</dd>\n' % (key, value) html += u'</dl>\n\n' html += u'<h4>Überweisungen</h4>\n<table>\n' ueberweisungen_summe = 0.0 speicher = Speicher(year) speicher.backend.db.execute('SELECT zeitpunkt, bezahlt, zahlung, name, summe FROM vorgang WHERE currentversion=1') data = speicher.backend.db.fetchall() for line in data: if not line['bezahlt'] and line['zahlung'] == 'ueberweisung': html += u'<tr><td>%s</td><td>%s</td><td>%.2f €</td></tr>\n' % (str(line['zeitpunkt'].date()), line['name'], line['summe']) ueberweisungen_summe += line['summe'] html += u'</table>' html += u'<p>Summe aller Überweisungen: %.2f €' % ueberweisungen_summe html += u'<h4>EC-Zahlungen</h4>\n<table>\n' ec_summe = 0.0 zahlungen = Speicher(year).backend.listAlleZahlungen() for z in zahlungen: if z['zahlart'] == 'ec': b = Speicher(year).ladeVorgang(z['vorgang']) html += u'<tr><td>%s</td><td>%s</td><td>%.2f €</td></tr>\n' % (str(z['timestamp'].date()), b.getKundenname(), z['betrag']) ec_summe += z['betrag'] html += u'</table>' html += u'<p>Summe aller EC-Zahlungen: %.2f €' % ec_summe # Alle Rohdaten html += u'<h4>Rohdaten</h4>\n<table>\n' pl = Preisliste() keys = sorted(list(stat.keys())) for key in keys: value = stat[key] desc = pl.getBeschreibung(key) if desc: desc = desc + ' (' + key + ')' try: html += u'<tr><td>%s</td><td>%s</td><td>%.2f €</td></tr>\n' % (desc, value, values[key]) except KeyError: pass html += u'</table>\n\n' return html
class WidgetAbfuellung(QtWidgets.QWidget): def __init__(self, mainwindow): QtWidgets.QWidget.__init__(self) self.mainwindow = mainwindow try: self.ui = uic.loadUi('ressource/ui/widget_abfuellung.ui', self) except: print('Kann UI-Datei nicht laden!') sys.exit(1) self.speicher = Speicher() self.pl = Preisliste() self.rabattStufen = [i[1] for i in self.pl.rabattStufen('5er')] while self.ui.combo_manuelleLiter.count() > 0: self.ui.combo_manuelleLiter.removeItem(0) for liter in self.rabattStufen: self.ui.combo_manuelleLiter.addItem('%s' % liter) self.connectSlots() self.stylesheetInputHighlighted = 'background-color: #faa; font-style: italic; border: 1px solid black;' self.stylesheetInputRegular = 'border: 1px solid black; background-color: white;' #for widget in self.ui.stackedWidget.findChildren(QtWidgets.QToolButton): # widget.setStyleSheet('border: 1px solid black;\nbackground-color: white;') self.ui.stackedWidget.widget(0).setStyleSheet( 'background-color: #96ff96;') self.ui.stackedWidget.widget(1).setStyleSheet( 'background-color: #ffffff;') self.ui.stackedWidget.widget(2).setStyleSheet( 'background-color: #9696ff;') self.ui.stackedWidget.widget(3).setStyleSheet( 'background-color: #ff9696;') self.alte_kundenvorgaenge = None self.liter_alte_abfuellungen = 0 self.rabattstufe_berechnen = True self.modus = 'speichern' self.neuerVorgang() def closeEvent(self, closeEvent): if self.vorgang.changed: if QtWidgets.QMessageBox.No == QtWidgets.QMessageBox.question( self, u'Änderungen verwerfen', u'Die aktuell geöffnete Abfüllung wurde noch nicht gespeichert. Trotzdem beenden?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No): closeEvent.ignore() def updateVorgang(self): if self.alte_kundenvorgaenge and self.rabattstufe_berechnen: liter_gesamt = self.liter_alte_abfuellungen + self.vorgang.getLiterzahl( ) stufe = 0 for s in self.rabattStufen: if liter_gesamt + self.pl.TOLERANZ >= s: stufe = s if stufe != self.vorgang.getManuelleLiterzahl(): self.vorgang.setManuelleLiterzahl(stufe) self.update() self.ui.listWidget.clear() for entry in self.vorgang.getEntries(): entry = ListEntry(self, entry) entry.itemChanged.connect(self.itemChanged) item = QtWidgets.QListWidgetItem() item.setSizeHint( QtCore.QSize(self.ui.listWidget.size().width() - 2, 60)) self.ui.listWidget.addItem(item) self.ui.listWidget.setItemWidget(item, entry) self.ui.listWidget.scrollToBottom() self.ui.label_gesamtpreis.setText(u'%.2f €' % self.vorgang.getSumme()) self.ui.label_literzahl.setText(u'%i Liter' % self.vorgang.getLiterzahl()) def isShown(self): self.rabattstufe_berechnen = True if not self.vorgang.kunde and self.modus == 'speichern': self.showKundenAuswahlDialog() def update(self): self.ui.stackedWidget.setCurrentIndex(0) self.ui.listWidget_kundenhinweise.clear() if self.vorgang.kunde.ID(): self.alte_kundenvorgaenge = self.speicher.listVorgaengeByKunde( self.vorgang.kunde.ID()) if self.alte_kundenvorgaenge: self.liter_alte_abfuellungen = 0 for b in self.alte_kundenvorgaenge: if b.ID == self.vorgang.ID: continue self.liter_alte_abfuellungen += b.getLiterzahl() hinweis = u'Abfüllung am %s: %s Liter' % (b.getZeitpunkt(), b.getLiterzahl()) self.ui.listWidget_kundenhinweise.addItem(hinweis) self.ui.listWidget_kundenhinweise.addItem( u'Vorherige Abfüllungen dieses Jahr insgesamt: %s Liter' % (self.liter_alte_abfuellungen, )) if self.vorgang.getKundenname() == '' and self.modus == 'speichern': self.ui.input_kundenname.setMinimumHeight(200) self.ui.input_kundenname.setStyleSheet( self.stylesheetInputHighlighted) self.ui.input_kundenname.setText(u'Hier Kunde wählen') else: self.ui.input_kundenname.setMinimumHeight(0) self.ui.input_kundenname.setStyleSheet(self.stylesheetInputRegular) self.ui.input_kundenname.setText( self.vorgang.getKundenname().replace('&', '&&')) if self.vorgang.getManuelleLiterzahl(): state_checkbox = self.ui.checkBox_manuelleLiter.blockSignals(True) state_combo = self.ui.combo_manuelleLiter.blockSignals(True) self.ui.checkBox_manuelleLiter.setChecked(True) self.ui.combo_manuelleLiter.setEnabled(True) self.ui.checkBox_manuelleLiter.setStyleSheet('color: #f00;') index = self.ui.combo_manuelleLiter.findText( str(self.vorgang.getManuelleLiterzahl())) self.ui.combo_manuelleLiter.setCurrentIndex(index) self.ui.checkBox_manuelleLiter.blockSignals(state_checkbox) self.ui.combo_manuelleLiter.blockSignals(state_combo) else: self.ui.checkBox_manuelleLiter.setChecked(False) self.ui.checkBox_manuelleLiter.setStyleSheet('color: #000;') self.ui.combo_manuelleLiter.setEnabled(False) self.ui.combo_manuelleLiter.setCurrentIndex( self.ui.combo_manuelleLiter.count() - 1) self.updateVorgang() def itemChanged(self): self.updateVorgang() def removeListEntryCallback(self): return lambda: self.ui.tableWidget.removeRow(self.ui.tableWidget. currentRow()) def newDoubleEntry(self, id1, id2, default2=None): def function(): handle = self.vorgang.newItem(0, id1) entry = self.vorgang.getEntry(handle) icon = None text = None try: button = getattr(self.ui, 'button_%s' % id1) icon = button.icon() text = button.text() except: print('Keinen button gefunden für %s' % id1) pass if not showNumberInputDialog(entry, icon=icon, text=text) or entry['anzahl'] == 0: self.vorgang.deleteItem(handle) else: self.updateVorgang() anz = entry['anzahl'] if default2 != None: anz = default2 handle = self.vorgang.newItem(anz, id2) entry = self.vorgang.getEntry(handle) if not showNumberInputDialog( entry, gebrauchte=True, icon=icon, text=text) or entry['anzahl'] == 0: self.vorgang.deleteItem(handle) self.updateVorgang() return function def newEntryCallback(self, preislistenID): def showDialog(): handle = self.vorgang.newItem(0, preislistenID) entry = self.vorgang.getEntry(handle) icon = None text = None try: button = getattr(self.ui, 'button_%s' % preislistenID) icon = button.icon() text = button.text() except: print('Keinen button gefunden für %s' % preislistenID) pass if not showNumberInputDialog( entry, gebrauchte=False, icon=icon, text=text) or entry['anzahl'] == 0: self.vorgang.deleteItem(handle) self.updateVorgang() def insertSingleItem(): found = False for entry in self.vorgang.getEntries(): if entry.preislistenID == preislistenID: entry.setStueckzahl(entry.getStueckzahl() + 1) found = True break if not found: self.vorgang.newItem(1, preislistenID) self.updateVorgang() if preislistenID in [ 'frischsaft', 'frischsaft_q', 'saft_offen', '3er', '3er_q', 'ohnepressen' ]: return showDialog else: return insertSingleItem def newFreeEntry(self, initvalue=0.0): handle = self.vorgang.newItem(1) entry = self.vorgang.getEntry(handle) entry.setEinheit('') entry.setSteuersatz(19.0) entry.setBeschreibung( showTextInputDialog('Beschreibung', [ 'Gutschein', 'Mosten', 'Kleinteile', 'Obstankauf', 'Sonstiges', 'Zeitschriften', 'Mindermengenzuschlag', 'Anzahlung' ], '')) if entry.getBeschreibung() == '': del entry self.vorgang.deleteItem(handle) return entry.setPreis(initvalue) showValueInputDialog(entry) if entry.getSumme() == 0: del entry self.vorgang.deleteItem(handle) self.update() def newBetragEntry(self): # Positiver Betrag self.newFreeEntry(0.0) def newAbzugEntry(self): # Negativer Betrag self.newFreeEntry(-0.0) def showKundenAuswahlDialog(self): self.vorgang.setKunde(showKundenAuswahlDialog(self.vorgang.getKunde())) self.update() def editKundendaten(self): self.vorgang.kunde = showKundendatenDialog(self.vorgang.kunde) self.speicher.speichereKunde(self.vorgang.kunde) self.update() def setzeManuellePreiskategorie(self, nonsense=None): liter = None if self.ui.checkBox_manuelleLiter.isChecked(): self.rabattstufe_berechnen = False try: liter = int(self.ui.combo_manuelleLiter.currentText()) except ValueError: liter = None else: self.rabattstufe_berechnen = False self.vorgang.setManuelleLiterzahl(liter) self.update() def plausibilitaetsCheck(self): errors = [] _10er = 0 _5er = 0 _3er = 0 _3er_gebraucht = 0 _5er_gebraucht = 0 _10er_gebraucht = 0 for item in self.vorgang.getEntries(): if item.preislistenID == '3er_gebraucht': _3er_gebraucht += item['anzahl'] elif item.preislistenID == '5er_gebraucht': _5er_gebraucht += item['anzahl'] elif item.preislistenID == '10er_gebraucht': _10er_gebraucht += item['anzahl'] elif item.preislistenID and '3er' in item.preislistenID: _3er += item['anzahl'] elif item.preislistenID and '5er' in item.preislistenID: _5er += item['anzahl'] elif item.preislistenID and '10er' in item.preislistenID: _10er += item['anzahl'] if _3er_gebraucht > _3er: errors.append( u'Mehr gebrauchte 3er-Kartons als insgesamt abgefüllt wurden!') if _5er_gebraucht > _5er: errors.append( u'Mehr gebrauchte 5er-Kartons als insgesamt abgefüllt wurden!') if _10er_gebraucht > _10er: errors.append( u'Mehr gebrauchte 10er-Kartons als insgesamt abgefüllt wurden!' ) if self.vorgang.getSumme() < 0.0: errors.append( u'Betrag ist Negativ, es wird eine Gutschrift erstellt!') if self.vorgang.getSumme() == 0.0: errors.append(u'Betrag ist 0!') return errors def speichern(self): self.speicher.speichereVorgang(self.vorgang) def regalschilder_drucken(self): for i in range(self.vorgang.getPaletten()): if not RegalschildThermo(self.vorgang, self.mainwindow.printer): QtWidgets.QMessageBox.warning( self, u'Fehler beim Drucken', 'Drucker nicht angeschlossen, nicht eingeschaltet oder Rechte falsch?', buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok) break def beleg_drucken(self): if not VorgangThermo(self.vorgang, self.mainwindow.printer): QtWidgets.QMessageBox.warning( self, u'Fehler beim Drucken', 'Drucker nicht angeschlossen, nicht eingeschaltet oder Rechte falsch?', buttons=QtWidgets.QMessageBox.Ok, defaultButton=QtWidgets.QMessageBox.Ok) #pdfdata = BelegA5(self.vorgang) #t = tempfile.NamedTemporaryFile(delete=False) #t.write(pdfdata) #t.close() #c = cups.Connection() #c.printFile(c.getDefault(), t.name, 'Vorgang %s' % self.vorgang.getKundenname(), PRINTER_OPTIONS) #subprocess.call(['/usr/bin/xdg-open', t.name], shell=False) # xdg-open beendet sich sofort! #os.unlink(t.name) def speichereVorgang(self): fehler = self.plausibilitaetsCheck() for f in fehler: if (QtWidgets.QMessageBox.No == QtWidgets.QMessageBox.warning( self, u'Möglicher Fehler', f + '\nIst das korrekt?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No)): return False dialog = SpeichernDialog(self.vorgang) dialog.show() dialog.exec_() if dialog.result() == 1: # OK gedrückt! if not dialog.speicherungErsetzen(): self.vorgang.setID(None) self.vorgang.setZeitpunkt(datetime.datetime.now()) self.speichern() if dialog.isBio: l = dialog.gewaehlterBioLieferschein() if l and not l['produktionsdatum']: l['produktionsdatum'] = datetime.date.today() self.speicher.speichereBioLieferschein(l) drucken = dialog.belegDrucken() if drucken: self.regalschilder_drucken() anrufe = self.speicher.getAnrufe(self.vorgang) if not anrufe and not dialog.kunde_nimmt_mit: telefon = self.vorgang.getTelefon() if telefon: for num in telefon.split(' / '): if num.startswith('+491') or num.startswith('01'): if (QtWidgets.QMessageBox.Yes == QtWidgets.QMessageBox.question( self, u'SMS senden?', u'Soll eine SMS an die Handynummer\n%s\ngesendet werden?' % num, buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)): try: send_sms(self.vorgang) except RuntimeError as e: QtWidgets.QMessageBox.warning( self, u'Fehler', str(e.args)) except ValueError as e: QtWidgets.QMessageBox.warning( self, u'Fehler', str(e.args)) else: self.speicher.speichereAnruf( self.vorgang, 'sms', '') break self.neuerVorgang() self.mainwindow.reset() self.update() def kassieren(self): fehler = self.plausibilitaetsCheck() for f in fehler: if (QtWidgets.QMessageBox.No == QtWidgets.QMessageBox.warning( self, u'Möglicher Fehler', f + '\nIst das korrekt?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No)): return False self.speichern() self.mainwindow.vorgangKassieren(self.vorgang) def neuerVorgang(self): self.vorgang = Vorgang() self.alte_kundenvorgaenge = None self.liter_alte_abfuellungen = 0 self.rabattstufe_berechnen = True self.modusSpeichern() self.update() def vorgangOeffnen(self, vorgang, kassiervorgang=False): self.vorgang = self.speicher.getVorgang(vorgang.ID) self.modusKassieren(kassiervorgang=kassiervorgang) self.update() return True def modusDirektverkauf(self): self.modus = 'kassieren' self.ui.button_speichern.setVisible(False) self.ui.button_kassieren.setVisible(True) self.ui.button_kassieren.setStyleSheet( 'background-color: #0f0; color: #000; border: 1px solid black;') self.ui.button_kassieren.setMinimumHeight(100) self.ui.button_kassieren.setText(u'Kassieren') def modusKassieren(self, kassiervorgang): self.modus = 'kassieren' if kassiervorgang: self.ui.button_speichern.setVisible(False) else: self.ui.button_speichern.setVisible(True) self.ui.button_speichern.setText(u'Nur Änderungen\nSpeichern') self.ui.button_speichern.setStyleSheet( 'border: 1px solid black; background-color: white;') self.ui.button_speichern.setMinimumHeight(100) self.ui.button_kassieren.setVisible(True) self.ui.button_kassieren.setText(u'Kassieren') self.ui.button_kassieren.setStyleSheet( 'background-color: #0f0; color: #000; border: 1px solid black;') self.ui.button_kassieren.setMinimumHeight(100) def modusSpeichern(self): self.modus = 'speichern' self.ui.button_speichern.setVisible(True) self.ui.button_speichern.setStyleSheet( 'background-color: #0f0; color: #000; border: 1px solid black;') self.ui.button_speichern.setMinimumHeight(100) self.ui.button_speichern.setText(u'Speichern') self.ui.button_kassieren.setVisible(False) def eventFilter(self, qobject, qevent): if qevent.type() == QtCore.QEvent.MouseButtonPress: qobject.clicked() return False def abbrechen(self): if self.vorgang.changed: if QtWidgets.QMessageBox.Yes == QtWidgets.QMessageBox.question( self, u'Alles Löschen', u'Wirklich alle Änderungen verwerfen und von vorne anfangen?', buttons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.No): if self.vorgang.ID: self.speicher.ladeVorgang(self.vorgang.ID) self.neuerVorgang() return True else: self.neuerVorgang() return True # Wenn die Frage von oben mit Nein beantwortet wurde return False def itemClicked(self, listItem): self.ui.listWidget.itemWidget(listItem).edit() def connectSlots(self): self.ui.label_kundenname.clicked = self.showKundenAuswahlDialog self.ui.label_kundenname.installEventFilter(self) self.ui.input_kundenname.clicked = self.showKundenAuswahlDialog self.ui.input_kundenname.installEventFilter(self) self.ui.button_kundendaten.clicked.connect(self.editKundendaten) self.ui.button_3er.clicked.connect(self.newEntryCallback('3er')) self.ui.button_5er.clicked.connect( self.newDoubleEntry('5er', '5er_gebraucht')) self.ui.button_10er.clicked.connect( self.newDoubleEntry('10er', '10er_gebraucht')) self.ui.button_frischsaft.clicked.connect( self.newEntryCallback('frischsaft')) self.ui.button_3er_q.clicked.connect(self.newEntryCallback('3er_q')) self.ui.button_5er_q.clicked.connect( self.newDoubleEntry('5er_q', '5er_gebraucht')) self.ui.button_10er_q.clicked.connect( self.newDoubleEntry('10er_q', '10er_gebraucht')) self.ui.button_frischsaft_q.clicked.connect( self.newEntryCallback('frischsaft_q')) self.ui.button_holzstaender_klassisch.clicked.connect( self.newEntryCallback('holzstaender_klassisch')) self.ui.button_holzstaender_5er_ablage.clicked.connect( self.newEntryCallback('holzstaender_eh_5er_ablage')) self.ui.button_holzstaender_5er_ohne.clicked.connect( self.newEntryCallback('holzstaender_eh_5er_ohne')) self.ui.button_holzstaender_10er.clicked.connect( self.newEntryCallback('holzstaender_eh_10er')) self.ui.button_unsersaft_5er.clicked.connect( self.newDoubleEntry('5er_abfuellung_vk', '5er_gebraucht')) self.ui.button_unsersaft_10er.clicked.connect( self.newDoubleEntry('10er_abfuellung_vk', '10er_gebraucht')) self.ui.button_vk_quittensaft_3er.clicked.connect( self.newEntryCallback('quitte_3er_vk')) self.ui.button_vk_quittensaft_5er.clicked.connect( self.newEntryCallback('quitte_5er_vk')) self.ui.button_vk5er.clicked.connect(self.newEntryCallback('5er_vk')) self.ui.button_vk10er.clicked.connect(self.newEntryCallback('10er_vk')) self.ui.button_vkbirnen.clicked.connect( self.newEntryCallback('birnen_5er_vk')) self.ui.button_vkbirnen_3er.clicked.connect( self.newEntryCallback('birnen_3er_vk')) self.ui.button_vkmost5er.clicked.connect( self.newEntryCallback('most_5er_vk')) self.ui.button_vkmost10er.clicked.connect( self.newEntryCallback('most_10er_vk')) self.ui.button_5lkanister.clicked.connect( self.newEntryCallback('kanister_5l')) self.ui.button_saft_offen.clicked.connect( self.newEntryCallback('saft_offen')) self.ui.button_obstler_025.clicked.connect( self.newEntryCallback('obstler_025')) self.ui.button_obstler_050.clicked.connect( self.newEntryCallback('obstler_050')) self.ui.button_obstler_100.clicked.connect( self.newEntryCallback('obstler_100')) self.ui.button_gelee_apfel.clicked.connect( self.newEntryCallback('gelee_apfel')) self.ui.button_gelee_apfel_zimt.clicked.connect( self.newEntryCallback('gelee_apfel_zimt')) self.ui.button_gelee_apfel_rum.clicked.connect( self.newEntryCallback('gelee_apfel_rum')) self.ui.button_gelee_quitten.clicked.connect( self.newEntryCallback('gelee_quitten')) self.ui.button_3er_gebraucht.clicked.connect( self.newEntryCallback('3er_gebraucht')) self.ui.button_5er_gebraucht.clicked.connect( self.newEntryCallback('5er_gebraucht')) self.ui.button_10er_gebraucht.clicked.connect( self.newEntryCallback('10er_gebraucht')) self.ui.button_ohnepressen.clicked.connect( self.newEntryCallback('ohnepressen')) self.ui.button_betrag.clicked.connect(self.newBetragEntry) self.ui.button_abzug.clicked.connect(self.newAbzugEntry) self.ui.button_speichern.clicked.connect(self.speichereVorgang) self.ui.button_kassieren.clicked.connect(self.kassieren) self.ui.checkBox_manuelleLiter.toggled.connect( self.setzeManuellePreiskategorie) self.ui.checkBox_manuelleLiter.toggled.connect( self.ui.combo_manuelleLiter.setEnabled) self.ui.combo_manuelleLiter.currentIndexChanged.connect( self.setzeManuellePreiskategorie) self.ui.listWidget.itemClicked.connect(self.itemClicked) self.ui.button_section_abfuellung.clicked.connect( lambda: self.ui.stackedWidget.setCurrentIndex(0)) self.ui.button_section_verkauf_saft.clicked.connect( lambda: self.ui.stackedWidget.setCurrentIndex(1)) self.ui.button_section_verkauf_sonstiges.clicked.connect( lambda: self.ui.stackedWidget.setCurrentIndex(2)) self.ui.button_section_besonderes.clicked.connect( lambda: self.ui.stackedWidget.setCurrentIndex(3))