import json from PyQt5.QtWidgets import QDialog from PyQt5.QtGui import QStandardItemModel, QStandardItem, QFont import ManageDB import ManageVendors from Settings import SettingsModel from ui import CostsTab, ReportTypeDialog from Constants import * from GeneralUtils import * class CostsController: """Controls the Costs tab :param costs_ui: the UI for the costs_widget :param settings: the user's settings""" def __init__(self, costs_ui: CostsTab.Ui_costs_tab, settings: SettingsModel): self.costs_ui = costs_ui self.settings = settings # set parameters self.report_parameter_combobox = costs_ui.costs_report_parameter_combobox self.report_parameter_combobox.addItems(REPORT_TYPE_SWITCHER.keys()) self.report_parameter = None self.vendor_parameter_combobox = costs_ui.costs_vendor_parameter_combobox self.vendor_parameter = None self.year_parameter_dateedit = costs_ui.costs_year_parameter_dateedit self.year_parameter_dateedit.setDate(QDate.currentDate()) self.year_parameter = None self.name_label = costs_ui.costs_name_parameter_label self.name_parameter_combobox = costs_ui.costs_name_parameter_combobox self.name_parameter = None # set up values self.cost_in_original_currency_doublespinbox = costs_ui.costs_cost_in_original_currency_doublespinbox self.cost_in_original_currency = 0.0 self.original_currency_combobox = costs_ui.costs_original_currency_value_combobox self.load_currency_list() self.original_currency = '' self.cost_in_local_currency_doublespinbox = costs_ui.costs_cost_in_local_currency_doublespinbox self.cost_in_local_currency = 0.0 self.cost_in_local_currency_with_tax_doublespinbox = \ costs_ui.costs_cost_in_local_currency_with_tax_doublespinbox self.cost_in_local_currency_with_tax = 0.0 # set up buttons self.save_costs_button = costs_ui.costs_save_button self.save_costs_button.clicked.connect(self.save_costs) self.load_button = costs_ui.costs_load_button self.load_button.clicked.connect(self.load_costs) self.clear_button = costs_ui.costs_clear_button self.clear_button.clicked.connect(self.clear_costs) vendors_json_string = read_json_file(ManageVendors.VENDORS_FILE_PATH) vendor_dicts = json.loads(vendors_json_string) self.vendor_parameter_combobox.clear() self.vendor_parameter_combobox.addItems([vendor_dict[NAME_KEY] for vendor_dict in vendor_dicts]) self.report_parameter_combobox.currentTextChanged.connect(self.on_report_parameter_changed) self.vendor_parameter_combobox.currentTextChanged.connect(self.on_vendor_parameter_changed) self.year_parameter_dateedit.dateChanged.connect(self.on_year_parameter_changed) self.name_parameter_combobox.currentTextChanged.connect(self.on_name_parameter_changed) self.names = [] self.costs_names = [] self.on_report_parameter_changed() self.year_parameter = int(self.year_parameter_dateedit.text()) self.vendor_parameter = self.vendor_parameter_combobox.currentText() self.fill_names() self.cost_in_original_currency_doublespinbox.valueChanged.connect(self.on_cost_in_original_currency_changed) self.original_currency_combobox.currentTextChanged.connect(self.on_original_currency_changed) self.cost_in_local_currency_doublespinbox.valueChanged.connect(self.on_cost_in_local_currency_changed) self.cost_in_local_currency_with_tax_doublespinbox.valueChanged.connect( self.on_cost_in_local_currency_with_tax_changed) self.import_costs_button = costs_ui.costs_import_costs_button self.import_costs_button.clicked.connect(self.import_costs) def update_settings(self, settings: SettingsModel): """Invoked when the settings are saved :param settings: the new settings""" self.settings = settings self.load_currency_list() def database_updated(self, code: int): """Invoked when the database is updated :param code: the exit code of the update""" self.fill_names() def load_vendor_list(self, vendors: Sequence[ManageVendors.Vendor]): """Updates the vendor list combobox :param vendors: the new list of vendors""" self.vendor_parameter_combobox.clear() self.vendor_parameter_combobox.addItems([vendor.name for vendor in vendors]) def load_currency_list(self): """Updates the original currency combobox""" self.original_currency_combobox.clear() self.original_currency_combobox.addItem(self.settings.default_currency) self.original_currency_combobox.addItems([currency for currency in CURRENCY_LIST if currency != self.settings.default_currency]) self.original_currency_combobox.setCurrentText('') def on_report_parameter_changed(self): """Invoked when the report parameter changes""" self.report_parameter = self.report_parameter_combobox.currentText() self.name_label.setText(NAME_FIELD_SWITCHER[self.report_parameter].capitalize()) if self.vendor_parameter: self.fill_names() def on_vendor_parameter_changed(self): """Invoked when the vendor parameter changes""" self.vendor_parameter = self.vendor_parameter_combobox.currentText() if self.report_parameter: self.fill_names() def on_year_parameter_changed(self): """Invoked when the year parameter changes""" self.year_parameter = int(self.year_parameter_dateedit.text()) self.load_costs() self.fill_names(True) def fill_names(self, only_get_costs_names: bool = False): """Fills the name field combobox""" self.name_parameter_combobox.clear() connection = ManageDB.create_connection(DATABASE_LOCATION) if connection is not None: if not only_get_costs_names: names_sql_text, names_data = ManageDB.get_names_sql_text(self.report_parameter, self.vendor_parameter) names_results = ManageDB.run_select_sql(connection, names_sql_text, names_data) if names_results: self.names = [result[0] for result in names_results] else: self.names = [] if self.settings.show_debug_messages: print(names_results) costs_sql_text, costs_data = ManageDB.get_names_with_costs_sql_text(self.report_parameter, self.vendor_parameter, self.year_parameter, self.year_parameter) costs_results = ManageDB.run_select_sql(connection, costs_sql_text, costs_data) connection.close() if costs_results: self.costs_names = [result[0] for result in costs_results] else: self.costs_names = [] if self.settings.show_debug_messages: print(costs_results) model = QStandardItemModel() for name in self.names: item = QStandardItem(name) if name in self.costs_names: font = QFont() font.setBold(True) item.setFont(font) model.appendRow(item) self.name_parameter_combobox.setModel(model) else: print('Error, no connection') def on_name_parameter_changed(self): """Invoked when the name field parameter changes""" self.name_parameter = self.name_parameter_combobox.currentText() enable = False if self.name_parameter: enable = True self.load_costs() self.cost_in_original_currency_doublespinbox.setEnabled(enable) self.original_currency_combobox.setEnabled(enable) self.cost_in_local_currency_doublespinbox.setEnabled(enable) self.cost_in_local_currency_with_tax_doublespinbox.setEnabled(enable) def on_cost_in_original_currency_changed(self): """Invoked when the cost in original currency parameter changes""" self.cost_in_original_currency = self.cost_in_original_currency_doublespinbox.value() def on_original_currency_changed(self): """Invoked when the original currency parameter changes""" self.original_currency = self.original_currency_combobox.currentText() def on_cost_in_local_currency_changed(self): """Invoked when the cost in local currency parameter changes""" self.cost_in_local_currency = self.cost_in_local_currency_doublespinbox.value() def on_cost_in_local_currency_with_tax_changed(self): """Invoked when the cost in local currency with tax parameter changes""" self.cost_in_local_currency_with_tax = self.cost_in_local_currency_with_tax_doublespinbox.value() def save_costs(self): """Saves the cost data: if it is nonzero, add it to the database; if it is zero, delete it from the database""" INSERT = 'insert' DELETE = 'delete' insert_or_delete = None sql_text = None data = None if self.cost_in_original_currency > 0 and self.original_currency != '' \ and self.cost_in_local_currency > 0 and self.cost_in_local_currency_with_tax > 0: insert_or_delete = INSERT elif self.cost_in_original_currency == 0 and self.original_currency == '' \ and self.cost_in_local_currency == 0 and self.cost_in_local_currency_with_tax == 0: insert_or_delete = DELETE if insert_or_delete == INSERT: sql_text, data = ManageDB.replace_costs_sql_text(self.report_parameter, ({NAME_FIELD_SWITCHER[self.report_parameter]: self.name_parameter, 'vendor': self.vendor_parameter, 'year': self.year_parameter, 'cost_in_original_currency': self.cost_in_original_currency, 'original_currency': self.original_currency, 'cost_in_local_currency': self.cost_in_local_currency, 'cost_in_local_currency_with_tax': self.cost_in_local_currency_with_tax},)) elif insert_or_delete == DELETE: sql_text, data = ManageDB.delete_costs_sql_text(self.report_parameter, self.vendor_parameter, self.year_parameter, self.name_parameter) if insert_or_delete in (INSERT, DELETE): connection = ManageDB.create_connection(DATABASE_LOCATION) if connection is not None: ManageDB.run_sql(connection, sql_text, data) connection.close() ManageDB.backup_costs_data(self.report_parameter) if insert_or_delete == INSERT: show_message('Data inserted/replaced') elif insert_or_delete == DELETE: show_message('Data removed') else: show_message('Invalid entry') def load_costs(self): """Fills the costs fields with data from the database""" sql_text, data = ManageDB.get_costs_sql_text(self.report_parameter, self.vendor_parameter, self.year_parameter, self.name_parameter) results = [] connection = ManageDB.create_connection(DATABASE_LOCATION) if connection is not None: results = ManageDB.run_select_sql(connection, sql_text, data) if not results: results.append((0.0, '', 0.0, 0.0)) connection.close() values = {} index = 0 for field in COST_FIELDS: values[field[NAME_KEY]] = results[0][index] index += 1 self.cost_in_original_currency_doublespinbox.setValue(values['cost_in_original_currency']) self.original_currency_combobox.setCurrentText(values['original_currency']) self.cost_in_local_currency_doublespinbox.setValue(values['cost_in_local_currency']) self.cost_in_local_currency_with_tax_doublespinbox.setValue(values['cost_in_local_currency_with_tax']) self.cost_in_original_currency_doublespinbox.repaint() def clear_costs(self): """Empties the costs fields""" self.cost_in_original_currency_doublespinbox.setValue(0.0) self.original_currency_combobox.setCurrentText('') self.cost_in_local_currency_doublespinbox.setValue(0.0) self.cost_in_local_currency_with_tax_doublespinbox.setValue(0.0) def import_costs(self): """Import a file with costs data in it into the database""" report_type_dialog = QDialog() report_type_dialog_ui = ReportTypeDialog.Ui_report_type_dialog() report_type_dialog_ui.setupUi(report_type_dialog) report_type_dialog_ui.report_type_combobox.addItems(REPORT_TYPE_SWITCHER.keys()) report_type_dialog.show() if report_type_dialog.exec_(): report_type = report_type_dialog_ui.report_type_combobox.currentText() if report_type != '': file_name = choose_file(TSV_FILTER + CSV_FILTER) if file_name != '': ManageDB.insert_single_cost_file(report_type, file_name) ManageDB.backup_costs_data(report_type) show_message('File ' + file_name + ' imported') else: print('Error, no file location selected') else: print('Error, no report type selected')