def calculate(self): ''' calculate the migration ''' if not self.ui.recalculate_inhabitants_check.isChecked(): self.add_layer(toggle_if_exists=True) return sum_ew = sum(x or 0 for x in self.areas.values('ew')) if sum_ew == 0: QMessageBox.warning( self.ui, 'Fehler', 'Es wurden keine definierten Teilflächen mit ' 'der Nutzungsart "Wohnen" gefunden.') return job = EwMigrationCalculation(self.project) def on_close(): self.changed.emit() if not self.dialog.success: self.wanderung.table.truncate() self.ui.recalculate_inhabitants_check.setVisible(False) self.ui.recalculate_inhabitants_check.setChecked(True) return self.ui.recalculate_inhabitants_check.setVisible(True) self.ui.recalculate_inhabitants_check.setChecked(False) self.add_layer() self.setup_params() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close) self.dialog.show()
def clone_project(self): ''' clone the currently selected project ''' project = self.project_manager.active_project if not project: return name = f'{project.name}_kopie' existing_names = [p.name for p in self.project_manager.projects] while True: name, ok = QInputDialog.getText(self.ui, f'{project.name} kopieren', 'Name des neuen Projekts', text=name) if ok: if name in existing_names: QMessageBox.warning( self.ui, 'Hinweis', 'Ein Projekt mit diesem Namen ist ' 'bereits vorhanden') continue job = CloneProject(name, project, parent=self.ui) def on_success(project): self.ui.project_combo.addItem(project.name, project) self.ui.project_combo.setCurrentIndex( self.ui.project_combo.count() - 1) self.project_manager.active_project = project dialog = ProgressDialog(job, parent=self.ui, on_success=on_success) dialog.show() break
def kostenvergleich(self): ''' calculate the total costs and show a comparison to mean values as a bar chart. only executable if all areas have either housing or commerce as type of use ''' types_of_use = [area.nutzungsart for area in self.areas if area.nutzungsart != Nutzungsart.UNDEFINIERT.value] if ((Nutzungsart.WOHNEN.value not in types_of_use and Nutzungsart.GEWERBE.value not in types_of_use) or len(np.unique(types_of_use)) != 1): QMessageBox.warning( self.ui, 'Hinweis', 'Die Funktion steht nur für Projekte zur ' 'Verfügung, bei denen alle Teilflächen ' 'ausschließlich die Nutzung Wohnen bzw. Gewerbe haben.' ) return job = GesamtkostenErmitteln(self.project) def on_close(): if not self.dialog.success: return if types_of_use[0] == Nutzungsart.WOHNEN.value: diagram = VergleichWEDiagramm(project=self.project) else: diagram = VergleichAPDiagramm(project=self.project) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show()
def calculate_nodes(self): ''' calculate the traffic nodes. resets all nodes and results ''' if len(self.transfer_nodes) > 0: reply = QMessageBox.question( self.ui.transfer_node_parameter_group, 'Herkunfts-/Zielpunkt entfernen', 'Die Berechnung der Herkunfts-/Zielpunkte setzt alle ' 'vorhandenen Punkte und Berechnungen zurück.\n' 'Wollen Sie die Berechnung fortsetzen?', QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.No: return self.transfer_nodes.table.truncate() self.links.table.truncate() self.traffic_load.table.truncate() distance = self.ui.distance_input.value() job = TransferNodeCalculation(self.project, distance=distance) def on_success(res): self.draw_nodes() self.draw_itineraries(zoom_to=True) def on_close(): self.fill_node_combo() self.setup_weights() self.canvas.refreshAllLayers() dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, on_close=on_close) dialog.show()
def calculate(self): ''' calculate the impact of the changes to status quo and show the results as layers ''' job = Projektwirkung(self.project, recalculate=False) success, msg = job.validate_inputs() if not success: QMessageBox.warning(self.ui, 'Fehler', msg) return self.remove_results() def on_success(r): self.show_results() if not self.settings.show_result_layer_info: return msg_box = QMessageBox(self.ui) msg_box.setText( 'Die Ergebnislayer wurden dem QGIS-Layerbaum ' 'in der Gruppe "Projektwirkung" hinzugefügt. Nur der' ' oberste Ergebnislayer ist aktiviert.\n\n' 'Um die anderen Ergebnisse anzuzeigen, ' 'aktivieren Sie sie bitte manuell im Layerbaum.\n') check = QCheckBox('nicht wieder anzeigen') msg_box.setCheckBox(check) msg_box.exec() if check.isChecked(): self.settings.show_result_layer_info = False dialog = ProgressDialog(job, parent=self.ui, on_success=on_success) dialog.show()
def calculate(self): ''' calculate migration of jobs ''' if not self.ui.recalculate_jobs_check.isChecked(): self.add_layer(toggle_if_exists=True) return sum_ap = sum(x or 0 for x in self.areas.values('ap_gesamt')) if sum_ap == 0: # ToDo: actually there are just no jobs # (e.g. when manually set to zero) QMessageBox.warning( self.ui, 'Fehler', 'Es wurden keine definierten Teilflächen mit ' 'der Nutzungsart "Gewerbe" gefunden.') return job = SvBMigrationCalculation(self.project) def on_close(): self.changed.emit() if not self.dialog.success: self.wanderung.table.truncate() self.ui.recalculate_inhabitants_check.setVisible(False) self.ui.recalculate_inhabitants_check.setChecked(True) return self.ui.recalculate_jobs_check.setVisible(True) self.ui.recalculate_jobs_check.setChecked(False) self.add_layer() self.setup_params() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close) self.dialog.show()
def calculate(self): ''' calculate the property tax ''' job = GrundsteuerCalculation(self.project) def on_success(r): self.add_layer() self.changed.emit() self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show()
def calculate_gesamtkosten(self): ''' calculate total costs of infrastructure and show diagram of results ''' job = GesamtkostenErmitteln(self.project) def on_close(): if not self.dialog.success: return diagram = GesamtkostenDiagramm(project=self.project, years=GesamtkostenErmitteln.years) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show()
def calculate_kostentraeger(self): ''' calculations of cost shares ''' job = KostentraegerAuswerten(self.project) def on_close(): if not self.dialog.success: return # the years originate from gesamtkosten calculation diagram = KostentraegerDiagramm(project=self.project, years=GesamtkostenErmitteln.years) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show()
def read_osm(self): ''' query geoserver for markets in the study area and add them to the status quo markets ''' buffer = self.ui.osm_buffer_input.value() \ if self.ui.osm_buffer_check.isChecked() else 0 job = ReadOSMWorker(self.project, epsg=self.settings.EPSG, buffer=buffer, truncate=False) def on_success(r): self.nullfall_edit.fill_combo() self.nullfall_edit.add_layer(zoom_to=True) self.changed_edit.fill_combo() self.remove_results() dialog = ProgressDialog(job, parent=self.ui, on_success=on_success) dialog.show()
def calculate(self): ''' calculate the business tax ''' if len(BeschaeftigtenWanderung.features()) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Wanderungssalden ' '(Beschäftigte) durch.') return job = GewerbesteuerCalculation(self.project) def on_success(r): self.add_layer() self.changed.emit() self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show()
def calc_fam_ausgleich(self): ''' calculate the family compensation based on the income tax ''' if sum([abs(gem.einkommensteuer) for gem in self.gemeinden]) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Einkommensteuer ' 'durch.') return job = FamAusgleichCalculation(self.project) def on_success(r): self.add_fla_layer() self.reset_results(fields=['summe_einnahmen']) self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show()
def calc_einkommensteuer(self): ''' calculate the income tax based on the inhabitant migration ''' if len(self.migration_ew.wanderung) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Wanderungssalden ' '(Einwohner) durch.') return job = EinkommensteuerCalculation(self.project) def on_success(r): self.add_est_layer() self.reset_results( fields=['fam_leistungs_ausgleich', 'summe_einnahmen']) self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show()
def save(self): ''' write the current parameter values to the database ''' we_sum = 0 for bt in self.gebaeudetypen_base: feature = self.wohneinheiten.get(id_gebaeudetyp=bt.id, id_teilflaeche=self.area.id) if not feature: feature = self.wohneinheiten.add( id_gebaeudetyp=bt.id, id_teilflaeche=self.area.id) we = getattr(self.params, bt.param_we).value feature.we = we we_sum += we ew_je_we = getattr(self.params, bt.param_ew_je_we).value feature.ew_je_we = ew_je_we anteil_u18 = getattr(self.params, bt.param_anteil_u18).value feature.anteil_u18 = anteil_u18 cor_factor = ew_je_we / bt.Ew_pro_WE_Referenz feature.korrekturfaktor = cor_factor feature.name_gebaeudetyp = bt.NameGebaeudetyp feature.save() self.area.beginn_nutzung = self.params.beginn_nutzung.value self.area.aufsiedlungsdauer = self.params.aufsiedlungsdauer.value self.area.we_gesamt = we_sum Traffic.reset() MunicipalTaxRevenue.reset_wohnen() self.area.save() job = WohnenDevelopment(self.basedata, self.area) dialog = ProgressDialog( job, auto_close=True, parent=self.layout.parentWidget()) dialog.show()
def calculate_traffic(self): ''' calculate the traffic load ''' max_dist = getattr(self.settings, 'MAX_AREA_DISTANCE', None) points = [c.geom.asPoint() for c in self.connectors] xs = [p.x() for p in points] ys = [p.y() for p in points] if max_dist is not None: distances = [] for i in range(len(points)): for j in range(i): dist = np.linalg.norm( np.subtract((xs[i], ys[i]), (xs[j], ys[j]))) distances.append(dist) if distances and max(distances) > 2 * max_dist: QMessageBox.warning( self.ui, 'Hinweis', 'Der Abstand zwischen den Anbindungspunkten ist zu groß. ' 'Er darf für die Schätzung der Verkehrsbelastung jeweils ' f'nicht größer als {2 * max_dist} m sein!') return if len(self.traffic_load) == 0: recalculate = len(self.links) == 0 job = Routing(self.project, recalculate=recalculate) def on_success(res): if self.itinerary_output: self.itinerary_output.remove() self.draw_nodes() self.draw_traffic(zoom_to=True) self.setup_weights() dialog = ProgressDialog(job, parent=self.ui, on_success=on_success) dialog.show() else: self.draw_traffic(zoom_to=True, toggle_if_exists=True)
def read_template(self): ''' let the user select a template and load its entries to the status quo markets ''' filters = [ f'*{ext[0]}' for ext in MarketTemplate.template_types.values() ] path, f = QFileDialog.getOpenFileName( self.ui, 'Templatedatei öffnen', None, f'Templatedatei ({" ".join(filters)})') if path: def on_success(r): self.nullfall_edit.fill_combo() self.nullfall_edit.add_layer(zoom_to=True) self.changed_edit.fill_combo() self.remove_results() job = MarketTemplateImportWorker(path, self.project, epsg=self.settings.EPSG) dialog = ProgressDialog(job, parent=self.ui, on_success=on_success) dialog.show()
def create_project(self): ''' Open a dialog for setting up a new project and create the project based on this setup. Automatically set the new project as active project if successfully created ''' status, msg = self.project_manager.check_basedata() if status == 0: QMessageBox.warning(self.ui, 'Hinweis', msg) self.ui.project_combo.setCurrentIndex(0) return dialog = NewProjectDialog() ok, name, layer = dialog.show() if ok: job = ProjectInitialization(name, layer, self.project_manager.settings.EPSG, parent=self.ui) self.project_manager.load_basedata() def on_success(project): self.project_manager.active_project = project self.ui.project_combo.addItem(project.name, project) self.ui.project_combo.setCurrentIndex( self.ui.project_combo.count() - 1) def on_close(): if not dialog.success: # ToDo: after stopping the creation of a project the # connection often can't be closed anymore try: self.project_manager.remove_project(job.project) except PermissionError: pass dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, on_close=on_close) dialog.show()
class EinwohnerMigration(Migration): ''' migration of inhabitants ''' def __init__(self, project, ui, layer_group, canvas): super().__init__(project, ui, layer_group, canvas) self.ui.migration_inhabitants_button.clicked.connect(self.calculate) def load_content(self): super().load_content() self.wanderung = EinwohnerWanderung.features(create=True) self.ui.einwohner_parameter_group.setVisible(False) if len(self.wanderung) == 0: self.ui.recalculate_inhabitants_check.setChecked(True) self.ui.recalculate_inhabitants_check.setVisible(False) self.ui.einwohner_parameter_group.setVisible(False) else: self.setup_params() def calculate(self): ''' calculate the migration ''' if not self.ui.recalculate_inhabitants_check.isChecked(): self.add_layer(toggle_if_exists=True) return sum_ew = sum(x or 0 for x in self.areas.values('ew')) if sum_ew == 0: QMessageBox.warning( self.ui, 'Fehler', 'Es wurden keine definierten Teilflächen mit ' 'der Nutzungsart "Wohnen" gefunden.') return job = EwMigrationCalculation(self.project) def on_close(): self.changed.emit() if not self.dialog.success: self.wanderung.table.truncate() self.ui.recalculate_inhabitants_check.setVisible(False) self.ui.recalculate_inhabitants_check.setChecked(True) return self.ui.recalculate_inhabitants_check.setVisible(True) self.ui.recalculate_inhabitants_check.setChecked(False) self.add_layer() self.setup_params() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close) self.dialog.show() def setup_params(self): ''' set up migration settings for each muncipality in study area ''' if self.params: self.params.close() self.ui.einwohner_parameter_group.setVisible(True) layout = self.ui.einwohner_parameter_group.layout() clear_layout(layout) self.params = Params(layout, help_file='einnahmen_einwohner_wanderung.txt') self.df_wanderung = self.wanderung.to_pandas() randsummen = self.project.basedata.get_table('Wanderung_Randsummen', 'Einnahmen').features() factor_inner = randsummen.get(IDWanderungstyp=1).Anteil_Wohnen factor_outer = randsummen.get(IDWanderungstyp=2).Anteil_Wohnen project_ags = self.project_frame.ags project_gem = self.gemeinden.get(AGS=project_ags) wanderung = self.wanderung.get(AGS=project_ags) sum_ew = sum(x or 0 for x in self.areas.values('ew')) def update_salden(ags_changed): param = self.params[ags_changed] fixed = param.is_locked saldo = param.input.value idx = self.df_wanderung['AGS'] == ags_changed if fixed: fixed_fortzug = self.df_wanderung[np.invert(idx) & self.df_wanderung['fixed'] == True]['fortzug'].sum() # the rest of "fortzüge" that can be applied to this row min_value = fixed_fortzug - (sum_ew * factor_inner) saldo = max(saldo, min_value) zuzug = self.df_wanderung[idx]['zuzug'].values[0] self.df_wanderung.loc[idx, 'fortzug'] = zuzug - saldo self.df_wanderung.loc[idx, 'fixed'] = fixed self.df_wanderung.loc[idx, 'saldo'] = saldo self.df_wanderung = MigrationCalculation.calculate_saldi( self.df_wanderung, factor_inner, project_ags) for gemeinde_ags in self.df_wanderung['AGS'].values: param = self.params[gemeinde_ags] row = self.df_wanderung[self.df_wanderung['AGS'] == gemeinde_ags] param.input.blockSignals(True) param.input.value = row['saldo'].values[0] param.input.blockSignals(False) self.params.add(Title('Standortgemeinde des Projekts', bold=False)) spinbox = DoubleSpinBox(minimum=0, maximum=1000, step=1, lockable=True, locked=wanderung.fixed, reversed_lock=True) project_saldo = Param(wanderung.saldo, spinbox, repr_format='%+.2f', label=f' - {project_gem.GEN}', unit='Ew') self.params.add(project_saldo, name=project_ags) spinbox.changed.connect(lambda o: update_salden(project_ags)) spinbox.locked.connect(lambda o: update_salden(project_ags)) self.params.add(Seperator()) self.params.add(Title('Region um Standortgemeinde', bold=False)) for gemeinde in sorted(self.gemeinden, key=lambda x: x.GEN): ags = gemeinde.AGS if ags == project_ags: continue wanderung = self.wanderung.get(AGS=ags) if not wanderung: continue spinbox = DoubleSpinBox(minimum=-1000, maximum=0, step=1, lockable=True, locked=wanderung.fixed, reversed_lock=True) param = Param(wanderung.saldo, spinbox, label=f' - {gemeinde.GEN}', unit='Ew') self.params.add(param, name=ags) spinbox.changed.connect(lambda o, a=ags: update_salden(a)) spinbox.locked.connect(lambda o, a=ags: update_salden(a)) self.params.add(Seperator()) self.params.add( Param(-factor_outer * sum_ew, label='Restliches Bundesgebiet / Ausland', unit='Ew')) def save(): self.wanderung.update_pandas(self.df_wanderung) self.changed.emit() self.canvas.refreshAllLayers() self.params.show(title='Geschätzte Salden (Einwohner) bearbeiten', scrollable=True) self.params.changed.connect(save) def add_layer(self, toggle_if_exists=False): ''' show layer with migration of inhabitants ''' self.output = ProjectLayer.from_table(self.wanderung.table, groupname=self.layer_group) self.output.draw(label='Wanderungssalden Einwohner', style_file='einnahmen_einwohnerwanderung.qml', uncheck_siblings=True, redraw=not toggle_if_exists, toggle_if_exists=toggle_if_exists) if self.output.tree_layer.isVisible(): self.output.zoom_to()
class Gesamtkosten: ''' edit cost parameters and calculation of costs ''' def __init__(self, ui, project): self.ui = ui self.project = project self.ui.gesamtkosten_button.clicked.connect(self.calculate_gesamtkosten) self.netzelemente = self.project.basedata.get_table( 'Netze_und_Netzelemente', 'Kosten' ).features().filter(Typ='Linie') for i, netzelement in enumerate(self.netzelemente): net_element_id = netzelement.IDNetzelement radio = QRadioButton(netzelement.Netzelement) self.ui.kostenkennwerte_radio_grid.addWidget(radio, i // 2, i % 2) if i == 0: self.net_element_id = net_element_id radio.setChecked(True) radio.toggled.connect( lambda b, i=net_element_id: self.setup_net_element(i) ) def load_content(self): self.kostenkennwerte = KostenkennwerteLinienelemente.features( create=True) if len(self.kostenkennwerte) == 0: init_kostenkennwerte(self.project) self.setup_net_element(self.net_element_id) def calculate_gesamtkosten(self): ''' calculate total costs of infrastructure and show diagram of results ''' job = GesamtkostenErmitteln(self.project) def on_close(): if not self.dialog.success: return diagram = GesamtkostenDiagramm(project=self.project, years=GesamtkostenErmitteln.years) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show() def setup_net_element(self, net_element_id): ''' set up parameters to edit the costs per element and phase ''' self.net_element_id = net_element_id ui_group = self.ui.kostenkennwerte_params_group net_element_name = self.netzelemente.get( IDNetzelement=net_element_id).Netzelement ui_group.setTitle(net_element_name) layout = ui_group.layout() clear_layout(layout) net_element = self.kostenkennwerte.get(IDNetzelement=net_element_id) self.params = Params( layout, help_file='infrastruktur_kostenkennwerte.txt') self.params.euro_EH = Param( net_element.Euro_EH, DoubleSpinBox(), unit='€', label='Kosten der erstmaligen Herstellung \n' 'pro laufenden Meter' ) self.params.euro_BU = Param( net_element.Cent_BU / 100, DoubleSpinBox(), unit='€', label='Jährliche Kosten für Betrieb und Unterhaltung \n' 'pro laufenden Meter und Jahr' ) self.params.euro_EN = Param( net_element.Euro_EN, DoubleSpinBox(), unit='€', label='Kosten der Erneuerung \n' 'pro laufenden Meter und Erneuerungszyklus' ) self.params.lebensdauer = Param( net_element.Lebensdauer, SpinBox(minimum=1, maximum=1000), label='Lebensdauer: Jahre zwischen den Erneuerungszyklen', unit='Jahr(e)' ) self.params.show() self.params.changed.connect(lambda: self.save(net_element_id)) def save(self, net_element_id): ''' write the current values of the parameters to database ''' net_element = self.kostenkennwerte.get(IDNetzelement=net_element_id) net_element.Euro_EH = self.params.euro_EH.value net_element.Lebensdauer = self.params.lebensdauer.value net_element.Cent_BU = self.params.euro_BU.value * 100 net_element.Euro_EN = self.params.euro_EN.value net_element.save()
class MunicipalTaxRevenue(Domain): ''' domain-widget for analyzing the job and inhabitant migration and the resulting tax revenue changes ''' radius = 25000 ui_label = 'Kommunale Steuereinnahmen' ui_file = 'domain_07-KSt.ui' ui_icon = "images/iconset_mob/20190619_iconset_mob_domain_tax_1.png" layer_group = 'Wirkungsbereich 6 - Kommunale Steuereinnahmen' def setupUi(self): self.migration_ew = EinwohnerMigration(self.project, self.ui, self.layer_group, self.canvas) self.migration_svb = BeschaeftigtenMigration(self.project, self.ui, self.layer_group, self.canvas) self.grundsteuer = Grundsteuer(self.project, self.ui, self.layer_group) self.gewerbesteuer = Gewerbesteuer(self.project, self.ui, self.layer_group) self.areas = Teilflaechen.features() manual_path = os.path.join(self.settings.HELP_PATH, 'Anleitung_Kommunale_Steuereinnahmen.pdf') self.ui.manual_button.clicked.connect(lambda: open_file(manual_path)) result_help_path = os.path.join( self.settings.HELP_PATH, 'Hinweise_zur_Ergebnisinterpretation_Kommunale_Einnahmen.pdf') self.ui.result_help_button.clicked.connect( lambda: open_file(result_help_path)) self.ui.calc_einkommensteuer_button.clicked.connect( self.calc_einkommensteuer) self.ui.calc_fla_button.clicked.connect(self.calc_fam_ausgleich) self.ui.calc_umsatzsteuer_button.clicked.connect( self.calc_umsatzsteuer) self.ui.calc_gesamtsumme_button.clicked.connect(self.calc_gesamtsumme) self.migration_ew.changed.connect(lambda: self.reset_results(fields=[ 'grundsteuer', 'einkommensteuer', 'fam_leistungs_ausgleich', 'summe_einnahmen' ])) self.migration_svb.changed.connect(lambda: self.reset_results( fields=['gewerbesteuer', 'umsatzsteuer', 'summe_einnahmen'])) self.grundsteuer.changed.connect(lambda: self.reset_results( fields=['grundsteuer', 'summe_einnahmen'])) self.gewerbesteuer.changed.connect(lambda: self.reset_results( fields=['gewerbesteuer', 'umsatzsteuer', 'summe_einnahmen'])) def load_content(self): super().load_content() self.project_frame = Projektrahmendaten.features( project=self.project)[0] self.gemeinden = Gemeindebilanzen.features(create=True) if len(self.gemeinden) == 0: self.init_gemeinden() self.migration_ew.load_content() self.migration_svb.load_content() self.grundsteuer.load_content() self.gewerbesteuer.load_content() def init_gemeinden(self): ''' get the muncipalities around the project areas and store them ''' gemeinden = self.project.basedata.get_table('bkg_gemeinden', 'Basisdaten_deutschland') buffer_geom = self.project_frame.geom.buffer(self.radius, 5) gemeinden.spatial_filter(buffer_geom.asWkt()) # project table has some of the fields of the basedata table # (same names) common_fields = set([f.name for f in gemeinden.fields()]).intersection( [f.name for f in self.gemeinden.fields()]) for gemeinde in gemeinden: attrs = {} for field in common_fields: attrs[field] = gemeinde[field] attrs['geom'] = gemeinde['geom'] self.gemeinden.add(**attrs) def calc_einkommensteuer(self): ''' calculate the income tax based on the inhabitant migration ''' if len(self.migration_ew.wanderung) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Wanderungssalden ' '(Einwohner) durch.') return job = EinkommensteuerCalculation(self.project) def on_success(r): self.add_est_layer() self.reset_results( fields=['fam_leistungs_ausgleich', 'summe_einnahmen']) self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show() def calc_fam_ausgleich(self): ''' calculate the family compensation based on the income tax ''' if sum([abs(gem.einkommensteuer) for gem in self.gemeinden]) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Einkommensteuer ' 'durch.') return job = FamAusgleichCalculation(self.project) def on_success(r): self.add_fla_layer() self.reset_results(fields=['summe_einnahmen']) self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show() def calc_umsatzsteuer(self): ''' calculate the value added tax based on the business tax ''' if sum([abs(gem.gewerbesteuer) for gem in self.gemeinden]) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Gewerbesteuer ' 'durch.') return ust_base = self.basedata.get_table('USt_Kennwerte', 'Einnahmen').features()[0] factor_gst = ust_base.GemAnt_USt_EUR_pro_EUR_GewSt factor_svb = ust_base.GemANt_USt_EUR_pro_SvB for gem in self.gemeinden: wanderung = self.migration_svb.wanderung.get(AGS=gem.AGS) saldo = wanderung.saldo if wanderung else 0 ust = factor_gst * gem.gewerbesteuer + factor_svb * saldo rnd = 1000 if ust >= 500 else 100 ust = round(ust / rnd) * rnd gem.umsatzsteuer = ust gem.save() self.reset_results(fields=['summe_einnahmen']) self.add_ust_layer() def calc_gesamtsumme(self): ''' calculate the total change of tax revenue ''' tou = self.areas.values('nutzungsart') if (Nutzungsart.WOHNEN.value in tou and sum( [abs(gem.fam_leistungs_ausgleich) for gem in self.gemeinden]) == 0): QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung des ' 'Familienleistungsausgleichs durch.') return if ((Nutzungsart.GEWERBE.value in tou or Nutzungsart.EINZELHANDEL.value in tou) and sum([abs(gem.umsatzsteuer) for gem in self.gemeinden]) == 0): QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Umsatzsteuer ' 'durch.') return for gem in self.gemeinden: gem.summe_einnahmen = (gem.grundsteuer + gem.einkommensteuer + gem.gewerbesteuer + gem.umsatzsteuer + gem.fam_leistungs_ausgleich) gem.save() self.add_gesamt_layer() def add_est_layer(self): ''' show income tax layer ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Einkommensteuer', style_file='einnahmen_einkommensteuer.qml', filter="einkommensteuer != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() def add_fla_layer(self): ''' show family compensation layer ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Familienleistungsausgleich', style_file='einnahmen_fam_leistungs_ausgleich.qml', filter="fam_leistungs_ausgleich != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() def add_ust_layer(self): ''' show value added tax layer ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Umsatzsteuer', style_file='einnahmen_umsatzsteuer.qml', filter="umsatzsteuer != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() def add_gesamt_layer(self): ''' show layer with total changes in tax revenues ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Gesamtsumme Einnahmen', style_file='einnahmen_summe_einnahmen.qml', filter="summe_einnahmen != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() @classmethod def reset_results(cls, fields=[ 'grundsteuer', 'einkommensteuer', 'gewerbesteuer', 'umsatzsteuer', 'fam_leistungs_ausgleich', 'summe_einnahmen' ]): ''' remove the results and layers ''' bilanzen = Gemeindebilanzen.features(create=True) df_bilanzen = bilanzen.to_pandas() for field in fields: df_bilanzen[field] = None bilanzen.update_pandas(df_bilanzen) canvas = utils.iface.mapCanvas() canvas.refreshAllLayers() @classmethod def reset_gewerbe_einzelhandel(cls): ''' remove the results based on changes of business and retail trade ''' BeschaeftigtenWanderung.get_table(create=True).truncate() cls.reset_results(fields=[ 'grundsteuer', 'gewerbesteuer', 'umsatzsteuer', 'summe_einnahmen' ]) @classmethod def reset_wohnen(cls): ''' remove the results based on residential changes ''' EinwohnerWanderung.get_table(create=True).truncate() cls.reset_results(fields=[ 'grundsteuer', 'fam_leistungs_ausgleich', 'einkommensteuer', 'summe_einnahmen' ]) def close(self): self.migration_ew.close() self.grundsteuer.close() self.migration_svb.close() self.gewerbesteuer.close() super().close()
class Kostentraeger: ''' parameters and calculations of shares of infrastructural costs between different payers ''' def __init__(self, ui, project): self.ui = ui self.project = project self.ui.kostentraeger_button.clicked.connect( self.calculate_kostentraeger) self.default_kostenaufteilung = self.project.basedata.get_table( 'Kostenaufteilung_Startwerte', 'Kosten') self.kostenphasen = self.project.basedata.get_table( 'Kostenphasen', 'Kosten').features() self.aufteilungsregeln = self.project.basedata.get_table( 'Aufteilungsregeln', 'Kosten').features() self.applyable_aufteilungsregeln = self.project.basedata.get_table( 'Aufteilungsregeln_zu_Netzen_und_Phasen', 'Kosten').features() self.netzelemente = self.project.basedata.get_table( 'Netze_und_Netzelemente', 'Kosten', fields=['IDNetz', 'Netz'] ).features() df_netzelemente = self.netzelemente.to_pandas() del df_netzelemente['fid'] df_netzelemente.drop_duplicates(inplace=True) for i, (index, row) in enumerate(df_netzelemente.iterrows()): net_id = row['IDNetz'] net_name = row['Netz'] radio = QRadioButton(net_name) self.ui.kostenaufteilung_radio_grid.addWidget(radio, i // 2, i % 2) if i == 0: self.net_id = net_id radio.setChecked(True) radio.toggled.connect( lambda b, i=net_id: self.setup_kostenaufteilung(i)) def load_content(self): self.kostenaufteilung = Kostenaufteilung.features( create=True, project=self.project) # initialize empty project 'kostenaufteilungen' with the default ones if len(self.kostenaufteilung) == 0: for default in self.default_kostenaufteilung.features(): rule = self.aufteilungsregeln.get( IDAufteilungsregel=default.IDKostenregel) self.kostenaufteilung.add( Anteil_GSB=rule.Anteil_GSB, Anteil_GEM=rule.Anteil_GEM, Anteil_ALL=rule.Anteil_ALL, IDNetz=default.IDNetz, IDKostenphase=default.IDKostenphase ) self.setup_kostenaufteilung(self.net_id) def calculate_kostentraeger(self): ''' calculations of cost shares ''' job = KostentraegerAuswerten(self.project) def on_close(): if not self.dialog.success: return # the years originate from gesamtkosten calculation diagram = KostentraegerDiagramm(project=self.project, years=GesamtkostenErmitteln.years) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show() def setup_kostenaufteilung(self, net_id): ''' set up parameters to edit shares for a specific type of infrastructure ''' self.net_id = net_id ui_group = self.ui.kostenaufteilung_params_group net_name = self.netzelemente.filter(IDNetz=net_id)[0].Netz ui_group.setTitle(net_name) layout = ui_group.layout() clear_layout(layout) self.params = Params( layout, help_file='infrastruktur_kostenaufteilung.txt') field_names = ['Anteil_GSB', 'Anteil_GEM', 'Anteil_ALL'] labels = ['Kostenanteil der Grunstücksbesitzer/innen', 'Kostenanteil der Gemeinde', 'Netznutzer/innen und Tarifkundschaft'] def preset_changed(c, p): preset = c.get_data() if not preset: return for field_name in field_names: param = self.params.get(f'{p.Kostenphase}_{field_name}') param.input.value = preset[field_name] for i, phase in enumerate(self.kostenphasen): dependency = SumDependency(100) self.params.add(Title(phase.Kostenphase)) feature = self.kostenaufteilung.get( IDKostenphase=phase.IDKostenphase, IDNetz=net_id) preset_combo, options = self.create_presets( net_id, phase.IDKostenphase) param = Param(0, preset_combo, label='Vorschlagswerte') param.hide_in_overview = True self.params.add(param, name=f'{phase.Kostenphase}_presets') for j, field_name in enumerate(field_names): label = labels[j] slider = Slider(maximum=100, lockable=True) param = Param(feature[field_name], slider, label=label, unit='%') self.params.add( param, name=f'{phase.Kostenphase}_{field_name}') dependency.add(param) slider.changed.connect( lambda b, c=preset_combo, o=options: c.set_value(o[0])) if i != len(self.kostenphasen) - 1: self.params.add(Seperator(margin=0)) preset_combo.changed.connect( lambda b, c=preset_combo, p=phase: preset_changed(c, p)) self.params.show(title='Kostenaufteilung festlegen') self.params.changed.connect(lambda: self.save(net_id)) def create_presets(self, net_id: int, phase_id: int) -> tuple: ''' create a combobox with presets for shares for a specific phase and type of infrastructure element ''' applyable_rules = self.applyable_aufteilungsregeln.filter( IDNetz=net_id, IDPhase=phase_id) rules = [] for applyable_rule in applyable_rules: rule_id = applyable_rule.IDAufteilungsregel rule = self.aufteilungsregeln.get(IDAufteilungsregel=rule_id) rules.append(rule) options = (['Aufteilungsregel wählen'] + [rule.Aufteilungsregel for rule in rules]) preset_combo = ComboBox(options, [None] + rules) preset_combo.input.model().item(0).setEnabled(False) return preset_combo, options def save(self, net_id): ''' write the current settings of paramaters for a specific type of infrastructure element ''' for phase in self.kostenphasen: feature = self.kostenaufteilung.get( IDKostenphase=phase.IDKostenphase, IDNetz=net_id) for field_name in ['Anteil_GSB', 'Anteil_GEM', 'Anteil_ALL']: param = self.params[f'{phase.Kostenphase}_{field_name}'] feature[field_name] = param.value feature.save()
class Gewerbesteuer(QObject): ''' parameters and calculation of business tax ''' changed = pyqtSignal() def __init__(self, project, ui, layer_group): super().__init__() self.layer_group = layer_group self.project = project self.ui = ui self.ui.calc_gewerbesteuer_button.clicked.connect(self.calculate) self.params = None def load_content(self): self.gemeinden = Gemeindebilanzen.features(project=self.project) self.setup_params() def setup_params(self): if self.params: self.params.close() layout = self.ui.gewerbesteuer_hebesatz_param_group.layout() clear_layout(layout) self.params = Params(layout, help_file='einnahmen_gewerbesteuer_hebesätze.txt') self.params.add(Title('Hebesätze', bold=False)) for gemeinde in sorted(self.gemeinden, key=lambda x: x.GEN): spinbox = SpinBox(minimum=0, maximum=999, step=1) param = Param(gemeinde.Hebesatz_GewSt, spinbox, label=f' - {gemeinde.GEN}', unit='v.H.') self.params.add(param, name=gemeinde.AGS) def save(): self.changed.emit() for gemeinde in self.gemeinden: param = self.params[gemeinde.AGS] gemeinde.Hebesatz_GewSt = param.value gemeinde.save() self.params.show(title='Hebesätze Gewerbesteuer bearbeiten', scrollable=True) self.params.changed.connect(save) def calculate(self): ''' calculate the business tax ''' if len(BeschaeftigtenWanderung.features()) == 0: QMessageBox.warning( self.ui, 'Fehler', 'Bitte führen Sie zunächst die Schätzung der Wanderungssalden ' '(Beschäftigte) durch.') return job = GewerbesteuerCalculation(self.project) def on_success(r): self.add_layer() self.changed.emit() self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show() def add_layer(self): ''' show business tax layer ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Gewerbesteuer', style_file='einnahmen_gewerbesteuer.qml', filter="gewerbesteuer != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() def close(self): if self.params: self.params.close()
class InfrastructuralCosts(Domain): ''' domain-widget for the analysis of required infrastructure and its cost ''' ui_label = 'Infrastrukturfolgekosten' ui_file = 'domain_06-IFK.ui' ui_icon = ('images/iconset_mob/' '20190619_iconset_mob_domain_infrstucturalcosts_4.png') layer_group = 'Wirkungsbereich 5 - Infrastrukturfolgekosten' def setupUi(self): self.drawing = InfrastructureDrawing(self.ui, project=self.project, canvas=self.canvas, layer_group=self.layer_group) self.kostenaufteilung = Kostentraeger(self.ui, project=self.project) self.gesamtkosten = Gesamtkosten(self.ui, project=self.project) self.ui.kostenvergleich_button.clicked.connect(self.kostenvergleich) pdf_path = os.path.join( self.settings.HELP_PATH, 'Anleitung_Infrastrukturfolgekosten.pdf') self.ui.manual_button.clicked.connect(lambda: open_file(pdf_path)) # quite dumb, but expanding a groupbox sets all children to visible # but we don't want to see the collapsed widgets def hide_widgets(): self.ui.kostenaufteilung_button.setChecked(False) self.ui.kostenkennwerte_button.setChecked(False) self.ui.kostenaufteilung_widget.setVisible(False) self.ui.kostenkennwerte_widget.setVisible(False) self.ui.evaluation_groupbox.collapsedStateChanged.connect( hide_widgets) hide_widgets() def load_content(self): super().load_content() self.areas = Teilflaechen.features() self.drawing.load_content() self.kostenaufteilung.load_content() self.gesamtkosten.load_content() def kostenvergleich(self): ''' calculate the total costs and show a comparison to mean values as a bar chart. only executable if all areas have either housing or commerce as type of use ''' types_of_use = [area.nutzungsart for area in self.areas if area.nutzungsart != Nutzungsart.UNDEFINIERT.value] if ((Nutzungsart.WOHNEN.value not in types_of_use and Nutzungsart.GEWERBE.value not in types_of_use) or len(np.unique(types_of_use)) != 1): QMessageBox.warning( self.ui, 'Hinweis', 'Die Funktion steht nur für Projekte zur ' 'Verfügung, bei denen alle Teilflächen ' 'ausschließlich die Nutzung Wohnen bzw. Gewerbe haben.' ) return job = GesamtkostenErmitteln(self.project) def on_close(): if not self.dialog.success: return if types_of_use[0] == Nutzungsart.WOHNEN.value: diagram = VergleichWEDiagramm(project=self.project) else: diagram = VergleichAPDiagramm(project=self.project) diagram.draw() self.dialog = ProgressDialog(job, parent=self.ui, on_close=on_close, auto_close=True) self.dialog.show() def close(self): ''' close all parameters and drawing tools ''' if hasattr(self.kostenaufteilung, 'params'): self.kostenaufteilung.params.close() if hasattr(self.gesamtkosten, 'params'): self.gesamtkosten.params.close() self.drawing.close() super().close()
class Grundsteuer(QObject): ''' parameters and calculation of property tax ''' changed = pyqtSignal() def __init__(self, project, ui, layer_group): super().__init__() self.project = project self.ui = ui self.layer_group = layer_group self.ui.calc_grundsteuer_button.clicked.connect(self.calculate) self.hebesatz_params = None self.rohmiete_params = None self.sachwert_params = None self.bauvolumen_params = None def load_content(self): self.project_frame = Projektrahmendaten.features( project=self.project)[0] self.gemeinden = Gemeindebilanzen.features(project=self.project) self.grst_settings = GrundsteuerSettings.features(create=True) if len(self.grst_settings) == 0: self.init_grst_base_settings() self.grst_settings = self.grst_settings[0] self.areas = Teilflaechen.features(project=self.project) self.ew_wanderung = EinwohnerWanderung.features() self.svb_wanderung = BeschaeftigtenWanderung.features() self.setup_hebesatz() self.setup_rohmiete() self.setup_sachwert() self.setup_bauvolumen() def init_grst_base_settings(self): ''' initialize the parameters of the base settings ''' gemeinden = self.project.basedata.get_table( 'bkg_gemeinden', 'Basisdaten_deutschland').features() gem = gemeinden.get(AGS=self.project_frame.ags) is_new_bundesland = int(self.project_frame.ags) >= 11000000 attrs = { 'Hebesatz_GrStB': gem.Hebesatz_GrStB, 'is_new_bundesland': is_new_bundesland } startwerte = self.project.basedata.get_table( 'GrSt_Startwerte_Rohmieten_Bodenwert', 'Einnahmen').features() gem_typ_startwerte = startwerte.get(Gemeindetyp=gem.Gemeindetyp) common_fields = set([f.name for f in startwerte.fields()]).intersection( [f.name for f in self.grst_settings.fields()]) for field in common_fields: attrs[field] = gem_typ_startwerte[field] self.grst_settings.add(**attrs) def setup_hebesatz(self): ''' assessment rate parameters ''' if self.hebesatz_params: self.hebesatz_params.close() layout = self.ui.grundsteuer_hebesatz_param_group.layout() clear_layout(layout) self.hebesatz_params = Params( layout, help_file='einnahmen_grundsteuer_hebesatz.txt') self.hebesatz_params.hebesatz = Param( self.grst_settings.Hebesatz_GrStB, SpinBox(maximum=999, step=10), label='Hebesatz GrSt B Projektgemeinde', unit='v.H.') def save(): self.changed.emit() self.grst_settings.Hebesatz_GrStB = \ self.hebesatz_params.hebesatz.value self.grst_settings.save() self.hebesatz_params.show(title='Hebesatz bearbeiten') self.hebesatz_params.changed.connect(save) def setup_rohmiete(self): ''' gross rent parameters ''' tou = self.areas.values('nutzungsart') if self.grst_settings.is_new_bundesland \ or not Nutzungsart.WOHNEN.value in tou: self.ui.grundsteuer_rohmiete_param_group.setVisible(False) return self.ui.grundsteuer_rohmiete_param_group.setVisible(True) if self.rohmiete_params: self.rohmiete_params.close() layout = self.ui.grundsteuer_rohmiete_param_group.layout() clear_layout(layout) self.rohmiete_params = Params( layout, help_file='einnahmen_grundsteuer_rohmieten.txt') self.rohmiete_params.add( Title('Rohmiete 1964 in Euro pro Monat', bold=False)) self.rohmiete_params.efh = Param(self.grst_settings.EFH_Rohmiete / 100, DoubleSpinBox(minimum=0.3, maximum=5, step=0.05), label=f' - Einfamilienhaus', unit='€/m²') self.rohmiete_params.dhh = Param(self.grst_settings.DHH_Rohmiete / 100, DoubleSpinBox(minimum=0.3, maximum=5, step=0.05), label=f' - Doppelhaus', unit='€/m²') self.rohmiete_params.rhw = Param(self.grst_settings.RHW_Rohmiete / 100, DoubleSpinBox(minimum=0.3, maximum=5, step=0.05), label=f' - Reihenhaus', unit='€/m²') self.rohmiete_params.mfh = Param(self.grst_settings.MFH_Rohmiete / 100, DoubleSpinBox(minimum=0.3, maximum=5, step=0.05), label=f' - Mehrfamilienhaus', unit='€/m²') def save(): self.changed.emit() self.grst_settings.EFH_Rohmiete = round( self.rohmiete_params.efh.value * 100) self.grst_settings.DHH_Rohmiete = round( self.rohmiete_params.dhh.value * 100) self.grst_settings.RHW_Rohmiete = round( self.rohmiete_params.rhw.value * 100) self.grst_settings.MFH_Rohmiete = round( self.rohmiete_params.mfh.value * 100) self.grst_settings.save() self.rohmiete_params.show(title='Rohmieten bearbeiten') self.rohmiete_params.changed.connect(save) def setup_sachwert(self): ''' asset value parameters ''' tou = self.areas.values('nutzungsart') if not self.grst_settings.is_new_bundesland\ or not Nutzungsart.WOHNEN.value in tou: self.ui.grundsteuer_sachwert_param_group.setVisible(False) return if self.sachwert_params: self.sachwert_params.close() self.ui.grundsteuer_sachwert_param_group.setVisible(True) layout = self.ui.grundsteuer_sachwert_param_group.layout() clear_layout(layout) self.sachwert_params = Params( layout, help_file='einnahmen_grundsteuer_sachwertverfahren.txt') self.sachwert_params.add(Title('Sachwertverfahren', bold=False)) self.sachwert_params.bodenwert = Param( self.grst_settings.Bodenwert_SWV / 100, DoubleSpinBox(minimum=0.3, maximum=5, step=0.05), label=f' - Bodenwert 1935 pro m²', unit='€/m²') self.sachwert_params.flaeche = Param( self.grst_settings.qm_Grundstueck_pro_WE_EFH, SpinBox(minimum=300, maximum=2000, step=1), label=f' - mittl. Größe Einfamilienhausgrundstücke', unit='m²') def save(): self.changed.emit() self.grst_settings.Bodenwert_SWV = round( self.sachwert_params.bodenwert.value * 100) self.grst_settings.qm_Grundstueck_pro_WE_EFH = \ self.sachwert_params.flaeche.value self.grst_settings.save() self.sachwert_params.show(title='Sachwertverfahren bearbeiten') self.sachwert_params.changed.connect(save) def setup_bauvolumen(self): ''' construction volume parameters ''' tou = self.areas.values('nutzungsart') if not (Nutzungsart.GEWERBE.value in tou or Nutzungsart.EINZELHANDEL.value in tou): self.ui.grundsteuer_bauvolumen_param_group.setVisible(False) # set to 0 as a precaution to not put some old values into # the calculation self.grst_settings.Bueroflaeche = 0 self.grst_settings.Verkaufsraeume = 0 self.grst_settings.save() return self.ui.grundsteuer_bauvolumen_param_group.setVisible(True) if self.bauvolumen_params: self.bauvolumen_params.close() layout = self.ui.grundsteuer_bauvolumen_param_group.layout() clear_layout(layout) self.bauvolumen_params = Params( layout, help_file='einnahmen_grundsteuer_bauvolumen.txt') self.bauvolumen_params.add( Title( 'Gewerbe / Einzelhandel: Voraussichtliches ' 'Bauvolumen\n(Brutto-Grundfläche, BGF)', bold=False)) self.bauvolumen_params.bueroflaeche = Param( self.grst_settings.Bueroflaeche, SpinBox(minimum=0, maximum=99999, step=10), label=f' - Bürofläche', unit='m²') self.bauvolumen_params.verkaufsraeume = Param( self.grst_settings.Verkaufsraeume, SpinBox(minimum=0, maximum=99999, step=10), label=f' - Hallen und Verkaufsräume', unit='m²') def save(): self.changed.emit() self.grst_settings.Bueroflaeche = \ self.bauvolumen_params.bueroflaeche.value self.grst_settings.Verkaufsraeume = \ self.bauvolumen_params.verkaufsraeume.value self.grst_settings.save() self.bauvolumen_params.show( title='Voraussichtliches Bauvolumen bearbeiten') self.bauvolumen_params.changed.connect(save) def calculate(self): ''' calculate the property tax ''' job = GrundsteuerCalculation(self.project) def on_success(r): self.add_layer() self.changed.emit() self.dialog = ProgressDialog(job, parent=self.ui, on_success=on_success, auto_close=True) self.dialog.show() def add_layer(self): ''' show property tax layer ''' self.output = ProjectLayer.from_table(self.gemeinden.table, groupname=self.layer_group) self.output.draw(label='Grundsteuer', style_file='einnahmen_grundsteuer.qml', filter="grundsteuer != 'NULL'", uncheck_siblings=True, redraw=False) self.output.zoom_to() def close(self): if self.hebesatz_params: self.hebesatz_params.close() if self.rohmiete_params: self.rohmiete_params.close() if self.sachwert_params: self.sachwert_params.close() if self.bauvolumen_params: self.bauvolumen_params.close()