Ejemplo n.º 1
0
class CreateRecipeDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(CreateRecipeDialog, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)

        title = QtWidgets.QLabel("Crear receta")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.product_field = AutocapField("Producto a crear...")
        self.product_field.setFixedWidth(200)

        self.model_field = AutocapField("Modelo de producto...")
        self.model_field.setFixedWidth(200)

        fields_layout = QtWidgets.QHBoxLayout()
        fields_layout.addWidget(self.product_field)
        fields_layout.addWidget(self.model_field)

        groupbox = QtWidgets.QGroupBox("Componentes y cantidades")
        groupbox.setStyleSheet(generic_groupbox_normal_style)
        groupbox.setMinimumWidth(333)

        add_component_button = QtWidgets.QPushButton("+ Agregar componente")
        add_component_button.setShortcut("Alt+a")

        self.comps_holder_section = QtWidgets.QVBoxLayout()
        groupbox_inner_section = QtWidgets.QVBoxLayout()
        groupbox_inner_section_1 = QtWidgets.QHBoxLayout()
        groupbox_inner_section_1.addWidget(add_component_button)
        groupbox_inner_section_2 = QtWidgets.QHBoxLayout()
        groupbox_inner_section_2.addLayout(self.comps_holder_section)
        groupbox_inner_section.addLayout(groupbox_inner_section_1)
        groupbox_inner_section.addLayout(groupbox_inner_section_2)
        groupbox.setLayout(groupbox_inner_section)
        groupbox_section = QtWidgets.QHBoxLayout()
        groupbox_section.addStretch()
        groupbox_section.addWidget(groupbox)
        groupbox_section.addStretch()

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")
        back_button.setFixedWidth(200)

        execute_button = QtWidgets.QPushButton("Ejecutar »")
        execute_button.setShortcut("Alt+e")
        execute_button.setFixedWidth(200)

        bottom_layout = QtWidgets.QHBoxLayout()
        bottom_layout.addWidget(back_button)
        bottom_layout.addWidget(execute_button)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addLayout(fields_layout)
        layout.addLayout(groupbox_section)
        layout.addStretch(1)
        layout.addLayout(bottom_layout)
        layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)

        self.setLayout(layout)

        back_button.clicked.connect(self.close)
        add_component_button.clicked.connect(self.add_line)
        execute_button.clicked.connect(self.create_recipe)

    def add_line(self):
        single_line_section = QtWidgets.QHBoxLayout()
        component_field = AutocapField("Componente...")
        component_field.setFixedWidth(200)
        component_field.setFocus()
        component_field.set_completer(source="comps in stock")
        value_field = StockNumberField("Cantidad...")
        value_field.setFixedWidth(80)
        close_button = LineItemCloseButton(holder=self.comps_holder_section)
        single_line_section.addWidget(component_field)
        single_line_section.addWidget(value_field)
        single_line_section.addWidget(close_button)
        self.comps_holder_section.addLayout(single_line_section)

    def create_recipe(self):
        for i in [
                self.test_if_product_or_model_fields_are_empty,
                self.test_if_there_are_recipe_data,
                self.test_if_there_are_duplicates,
                self.test_if_there_are_unrecognized_components,
        ]:
            if i():
                return

        self.insert_new_recipe_into_db()

    def test_if_product_or_model_fields_are_empty(self):
        if self.product_field.text() == "":
            WarningBox("Producto faltante",
                       "Ingresar producto\nantes de ejecutar.").exec_()
            self.product_field.setFocus()
            return True
        elif self.model_field.text() == "":
            WarningBox("Modelo faltante",
                       "Ingresar modelo\nantes de ejecutar.").exec_()
            self.model_field.setFocus()
            return True
        else:
            return False

    def test_if_there_are_recipe_data(self):
        contents = utils.get_line_items_contents(self.comps_holder_section)
        empty_strings_exist = tests.test_if_empty_string_in_line_items_contents(
            contents)

        if self.comps_holder_section.children() and empty_strings_exist:
            WarningBox(
                "Sin componentes",
                "Completar o borrar campos\nvacíos antes de ejecutar.",
            ).exec_()
            return True
        else:
            return False

    def test_if_there_are_duplicates(self):
        contents = utils.get_line_items_contents(self.comps_holder_section)

        if tests.test_if_duplicated_first_value_in_line_items_contents(
                contents):
            WarningBox("Componentes duplicados",
                       "Borrar uno de los componentes duplicados.").exec_()
            return True
        else:
            return False

    def test_if_there_are_unrecognized_components(self):
        contents = utils.get_line_items_contents(self.comps_holder_section)

        incoming_components = contents[0::2]
        db = db_manager.DB_Manager()
        existing_comps = db.get_all_display_names_for_components()
        db.close_connection()

        if not set(incoming_components).issubset(existing_comps):
            WarningBox(
                "Componente extraño",
                "Componente no reconocido. Cargar el\ncomponente desde el autocompletado.",
            ).exec_()
            return True
        else:
            return False

    def insert_new_recipe_into_db(self):
        recipe_being_created_display = (self.product_field.text() + "-" +
                                        self.model_field.text())
        recipe_being_created_sql = utils.format_display_name_into_sql_name(
            recipe_being_created_display)
        fields_contents = utils.get_line_items_contents(
            self.comps_holder_section)
        components = fields_contents[0::2]
        amounts = fields_contents[1::2]
        recipe_contents = dict(zip(components, amounts))

        db = db_manager.DB_Manager()
        db.create_recipe(recipe_being_created_sql)
        db.populate_recipe(recipe_being_created_sql, recipe_contents)
        db.log_new_config_record(config="Creación de receta",
                                 details=recipe_being_created_display)
        db.close_connection()

        admin_window = self.parent().parent().parent()
        admin_window.statusbar.show_quick_message("Receta creada: " +
                                                  recipe_being_created_display)

        self.close()
Ejemplo n.º 2
0
class DeleteComponentDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(DeleteComponentDialog, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)
        self.setFixedWidth(200)

        self.comp_being_deleted_display_name = ""

        title = QtWidgets.QLabel("Borrar componente")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.search_field = AutocapField("Buscar componente a borrar...")
        self.search_field.setFocus()
        self.search_field.set_completer(source="comps in stock")

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")

        execute_button = QtWidgets.QPushButton("Ejecutar »")
        execute_button.setShortcut("Alt+e")
        execute_button.setDefault(True)

        bottom_section = QtWidgets.QHBoxLayout()
        bottom_section.addWidget(back_button)
        bottom_section.addWidget(execute_button)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(self.search_field)
        layout.addLayout(bottom_section)

        self.setLayout(layout)

        self.search_field.returnPressed.connect(self.delete_component)
        execute_button.clicked.connect(self.delete_component)
        back_button.clicked.connect(self.close)

    def test_if_there_are_unrecognized_components(self):
        db = db_manager.DB_Manager()
        existing_comps = db.get_all_display_names_for_components()
        db.close_connection()

        if self.search_field.text() not in existing_comps:
            WarningBox(
                "Componente extraño",
                "Componente no reconocido. Cargar el\ncomponente desde el autocompletado.",
            ).exec_()
            return True
        else:
            return False

    def delete_component(self):
        if self.test_if_there_are_unrecognized_components():
            return
        self.comp_being_deleted_display_name = self.search_field.text()
        main_section_table = self.parent().parent().main_section.table
        utils.scroll_to_row_in_table(
            main_section_table,
            (self.comp_being_deleted_display_name),
            keep_light_blue_color=True,
        )
        DeletionConfirmationBox(parent=self).exec_()
Ejemplo n.º 3
0
class EditRecipeDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(EditRecipeDialog, self).__init__(parent)

        self.recipe_being_edited_display = ""
        self.recipe_being_edited_sql = ""
        self.stored_recipe_contents = {}

        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)

        self.setFixedWidth(200)
        self.setFixedHeight(250)

        title = QtWidgets.QLabel("Editar receta")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.searchbar = AutocapField("Buscar receta a editar...")
        self.searchbar.set_completer(source="recipes")

        self.table = QtWidgets.QTableWidget()
        self.table.setFocusPolicy(QtCore.Qt.NoFocus)
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table.verticalHeader().setVisible(False)
        self.table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.table.setColumnCount(1)
        self.table.setHorizontalHeaderLabels(["Producto"])
        self.table.horizontalHeaderItem(0).setTextAlignment(
            QtCore.Qt.AlignHCenter)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QtWidgets.QHeaderView.Stretch)

        db = db_manager.DB_Manager()
        self.all_recipes_display = db.get_all_recipes_as_display()
        db.close_connection()
        self.table.setRowCount(len(self.all_recipes_display))
        utils.populate_table_column_with_list_of_strings(
            table=self.table, col_num=0, input_list=self.all_recipes_display)

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(self.searchbar)
        layout.addWidget(self.table)
        layout.addWidget(back_button)

        self.setLayout(layout)

        back_button.clicked.connect(self.close)
        self.searchbar.returnPressed.connect(self.on_searchbar_return_pressed)
        self.table.cellDoubleClicked.connect(self.on_table_item_double_clicked)

        if not self.all_recipes_display:
            InformationBox("Sin recetas",
                           "No hay recetas para editar.").exec_()
            QtCore.QTimer.singleShot(1, self.close)

    def on_searchbar_return_pressed(self):
        if self.searchbar.text() not in self.all_recipes_display:
            return
        utils.scroll_to_row_in_table(self.table, self.searchbar.text())
        self.recipe_being_edited_display = self.searchbar.text()
        RecipeDetailsDialog(parent=self).exec_()

    def on_table_item_double_clicked(self, row, col):
        self.recipe_being_edited_display = self.table.item(row, col).text()
        RecipeDetailsDialog(parent=self).exec_()
Ejemplo n.º 4
0
class EditComponentDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(EditComponentDialog, self).__init__(parent)
        self.setWindowFlags(
            QtCore.Qt.Dialog
            | QtCore.Qt.CustomizeWindowHint
            | QtCore.Qt.WindowCloseButtonHint
        )
        self.setFixedWidth(200)
        self.setFixedHeight(250)

        self.comp_being_edited = ""

        title = QtWidgets.QLabel("Editar componente")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.searchbar = AutocapField("Buscar componente a editar...")
        self.searchbar.set_completer(source="comps in stock")

        self.comps_table = QtWidgets.QTableWidget()
        self.comps_table.setColumnCount(1)
        self.comps_table.setHorizontalHeaderLabels(["Componente"])
        self.comps_table.setFocusPolicy(QtCore.Qt.NoFocus)
        self.comps_table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.comps_table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.comps_table.verticalHeader().setVisible(False)
        self.comps_table.horizontalHeaderItem(0).setTextAlignment(
            QtCore.Qt.AlignHCenter
        )
        self.comps_table.horizontalHeader().setSectionResizeMode(
            0, QtWidgets.QHeaderView.Stretch
        )

        db = db_manager.DB_Manager()
        self.existing_comps = db.get_all_display_names_for_components()

        self.comps_table.setRowCount(len(self.existing_comps))
        utils.populate_table_column_with_list_of_strings(
            table=self.comps_table, col_num=0, input_list=self.existing_comps
        )
        self.comps_table.setSortingEnabled(True)
        self.comps_table.horizontalHeader().setSortIndicator(
            0, QtCore.Qt.AscendingOrder
        )
        self.comps_table.horizontalHeader().setSortIndicatorShown(False)

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(self.searchbar)
        layout.addWidget(self.comps_table)
        layout.addWidget(back_button)

        self.setLayout(layout)

        self.searchbar.returnPressed.connect(self.on_searchbar_return_pressed)
        self.comps_table.cellDoubleClicked.connect(self.on_table_item_double_clicked)
        back_button.clicked.connect(self.close)

        if not self.existing_comps:
            InformationBox("Sin componentes", "No hay componentes para editar.").exec_()
            QtCore.QTimer.singleShot(1, self.close)

    def on_searchbar_return_pressed(self):
        if self.searchbar.text() not in self.existing_comps:
            return
        utils.scroll_to_row_in_table(self.comps_table, self.searchbar.text())
        self.comp_being_edited = self.searchbar.text()
        EditInputDialog(parent=self).exec_()

    def on_table_item_double_clicked(self, row):
        self.comp_being_edited = self.comps_table.item(row, 0).text()
        EditInputDialog(parent=self).exec_()
Ejemplo n.º 5
0
class CreateComponentDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(CreateComponentDialog, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)

        title = QtWidgets.QLabel("Crear componente")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.compname_field = AutocapField("Componente a crear...")
        self.compname_field.setFixedWidth(150)
        self.compname_field.setFocus()

        self.initstock_field = StockNumberField("Stock inicial...")
        self.initstock_field.setFixedWidth(80)

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")

        self.execute_button = QtWidgets.QPushButton("Ejecutar »")
        self.execute_button.setDefault(True)

        line_edits_layout = QtWidgets.QHBoxLayout()
        line_edits_layout.addWidget(self.compname_field)
        line_edits_layout.addWidget(self.initstock_field)

        bottom_section = QtWidgets.QHBoxLayout()
        bottom_section.addWidget(back_button)
        bottom_section.addWidget(self.execute_button)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addLayout(line_edits_layout)
        layout.addLayout(bottom_section)

        self.setLayout(layout)

        back_button.clicked.connect(self.close)
        self.execute_button.clicked.connect(self.create_component)

    def create_component(self):
        if self.compname_field.text() == "":
            message_boxes.WarningBox(
                "Sin nombre",
                "Dar nombre al componente\nantes de ejecutar.").exec_()
            self.compname_field.setFocus()
            return

        db = db_manager.DB_Manager()
        component_names_display = db.get_all_display_names_for_components()

        if self.compname_field.text() in component_names_display:
            message_boxes.WarningBox(
                "Nombre ya existente",
                "El nombre tiene que ser\ndiferente de los existentes.",
            ).exec_()
            self.compname_field.clear()
            self.compname_field.setFocus()
            return

        newcomp_display_name = self.compname_field.text()
        newcomp_sql_name = utils.format_display_name_into_sql_name(
            newcomp_display_name)

        initstock = 0
        if self.initstock_field.text() != "":
            initstock = utils.format_number_for_calculation(
                self.initstock_field.text())

        db.create_new_component(newcomp_sql_name, newcomp_display_name,
                                initstock)
        db.log_new_config_record(config="Creación de componente",
                                 details=newcomp_display_name)
        db.close_connection()

        admin_window = self.parent().parent().parent()
        admin_window.statusbar.show_quick_message("Componente creado: " +
                                                  newcomp_display_name)
        admin_window.start_screen.rebuild_main_section()

        QtWidgets.QApplication.processEvents()  # enables scrolling
        table = admin_window.start_screen.main_section.table
        utils.scroll_to_row_in_table(table, newcomp_display_name)

        self.compname_field.clear()
        self.initstock_field.clear()
        self.close()
Ejemplo n.º 6
0
class MainSection(QtWidgets.QWidget):
    def __init__(self):
        super(MainSection, self).__init__()

        self.selected_comp_display = ""
        self.selected_comp_SQL = ""

        title = QtWidgets.QLabel("Resumen de componentes")
        title.setStyleSheet(main_section_title_style)
        title.setAlignment(QtCore.Qt.AlignCenter)

        self.searchbar = AutocapField("Buscar componente...")
        self.searchbar.set_completer(source="comps in stock")

        sb_shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("Alt+b"),
                                          self.searchbar)
        sb_shortcut.activated.connect(self.searchbar.setFocus)

        self.update_button = QtWidgets.QPushButton("Actualizado")
        self.update_button.setShortcut("Alt+a")
        self.update_button.setFixedWidth(110)
        self.update_button.setEnabled(False)

        primary_button = QtWidgets.QToolButton()
        primary_button.setIcon(qta.icon("mdi.view-list"))
        primary_button.setText("Cuadro de inventario")
        primary_button.setShortcut("Alt+p")

        secondary_button = QtWidgets.QToolButton()
        secondary_button.setIcon(qta.icon("mdi.file-tree"))
        secondary_button.setText("Cuadros secundarios")
        secondary_button.setShortcut("Alt+s")

        for i in [primary_button, secondary_button]:
            i.setIconSize(QtCore.QSize(42, 42))
            i.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)
            i.setSizePolicy(QtWidgets.QSizePolicy.Preferred,
                            QtWidgets.QSizePolicy.Expanding)
            i.setPopupMode(QtWidgets.QToolButton.InstantPopup)
            i.setFixedHeight(70)
            i.setFixedWidth(126)

        primary_menu = QtWidgets.QMenu()
        primary_menu_item_1 = primary_menu.addAction("Resaltar críticos")
        primary_menu_item_2 = primary_menu.addAction("Resaltar excluidos")
        primary_menu_item_3 = primary_menu.addAction("Exportar datos")
        primary_menu.setStyleSheet(main_section_menu_style)
        primary_button.setMenu(primary_menu)

        secondary_menu = QtWidgets.QMenu()
        secondary_menu.setStyleSheet(main_section_menu_style)
        secondary_menu_item_1 = secondary_menu.addAction("Movimientos")
        secondary_menu_item_2 = secondary_menu.addAction("Configuraciones")
        secondary_button.setMenu(secondary_menu)

        horizontal_section_layout = QtWidgets.QHBoxLayout()
        horizontal_section_layout.addWidget(self.searchbar)
        horizontal_section_layout.addWidget(self.update_button)

        table_layout = QtWidgets.QVBoxLayout()
        self.table = QtWidgets.QTableWidget()
        self.table.setStyleSheet(main_section_table_style)
        self.table.setColumnCount(6)
        self.table.setFixedHeight(355)
        self.table.setFocusPolicy(QtCore.Qt.NoFocus)
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.table.verticalHeader().setVisible(False)
        self.main_section_header_labels = [
            "Componente",
            "Total",
            "Depósito",
            "Karina",
            "Brid",
            "Tercero",
        ]
        self.table.setHorizontalHeaderLabels(self.main_section_header_labels)
        self.table.horizontalHeader().setDefaultSectionSize(70)

        self.table.horizontalHeader().setSectionResizeMode(
            0, QtWidgets.QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QtWidgets.QHeaderView.Fixed)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QtWidgets.QHeaderView.Fixed)
        self.table.horizontalHeader().setSectionResizeMode(
            3, QtWidgets.QHeaderView.Fixed)
        self.table.horizontalHeader().setSectionResizeMode(
            4, QtWidgets.QHeaderView.Fixed)
        self.table.horizontalHeader().setSectionResizeMode(
            5, QtWidgets.QHeaderView.Fixed)

        for i in range(6):
            self.table.horizontalHeaderItem(i).setTextAlignment(
                QtCore.Qt.AlignHCenter)

        table_layout.addWidget(self.table)
        layout = QtWidgets.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        header_layout = QtWidgets.QHBoxLayout()
        header_left_layout = QtWidgets.QVBoxLayout()
        header_right_layout = QtWidgets.QHBoxLayout()
        header_left_layout.addWidget(title)
        header_left_layout.addLayout(horizontal_section_layout)
        header_right_layout.addWidget(primary_button)
        header_right_layout.addWidget(secondary_button)
        header_layout.addLayout(header_left_layout)
        header_layout.addLayout(header_right_layout)

        layout.addLayout(header_layout)
        layout.addLayout(table_layout)

        self.setLayout(layout)

        db = db_manager.DB_Manager()
        total_table_count = db.get_total_table_count()
        stocks_1 = db.get_stocks_for_owner("stock_valdenegro")
        stocks_2 = db.get_stocks_for_owner("stock_karina")
        stocks_3 = db.get_stocks_for_owner("stock_brid")
        stocks_4 = db.get_stocks_for_owner("stock_tercero")
        self.all_components_display = db.get_all_display_names_for_components()
        self.stored_criticals = db.get_stored_criticals()
        self.unused_comps = db.get_components_not_in_use()
        db.close_connection()

        settings = QtCore.QSettings("solutronic", "admin_stock")
        self.excluded_state = settings.value("excluded_checkbox")

        stocks_g = []
        for i in range(total_table_count):
            result = stocks_1[i] + stocks_2[i] + stocks_3[i] + stocks_4[i]
            stocks_g.append(result)

        self.table.setRowCount(total_table_count)

        stocks_g_display = [
            utils.format_number_for_display(i) for i in stocks_g
        ]
        stocks_1_display = [
            utils.format_number_for_display(i) for i in stocks_1
        ]
        stocks_2_display = [
            utils.format_number_for_display(i) for i in stocks_2
        ]
        stocks_3_display = [
            utils.format_number_for_display(i) for i in stocks_3
        ]
        stocks_4_display = [
            utils.format_number_for_display(i) for i in stocks_4
        ]

        for count, value in enumerate([
                self.all_components_display,
                stocks_g_display,
                stocks_1_display,
                stocks_2_display,
                stocks_3_display,
                stocks_4_display,
        ]):
            utils.populate_table_column_with_list_of_strings(table=self.table,
                                                             col_num=count,
                                                             input_list=value)

        utils.color_criticals_in_orange_in_main_section(
            self.table, self.stored_criticals)
        utils.color_zeros_in_grey_in_main_section(self.table,
                                                  self.stored_criticals)
        utils.color_excluded_in_yellow_in_main_section(self.table,
                                                       self.excluded_state,
                                                       self.unused_comps)

        self.searchbar.returnPressed.connect(self.get_searched_component)
        primary_menu_item_1.triggered.connect(
            lambda: CriticalCompsDialog(self).exec_())
        primary_menu_item_2.triggered.connect(
            lambda: ExcludedCompsDialog(self).exec_())
        primary_menu_item_3.triggered.connect(self.export_to_spreadsheet)
        secondary_menu_item_1.triggered.connect(
            lambda: MovementsDialog(self).exec_())
        secondary_menu_item_2.triggered.connect(
            lambda: ConfigsDialog(self).exec_())
        self.table.horizontalHeader().sortIndicatorChanged.connect(
            self.sort_components_alphabetically)
        self.table.cellDoubleClicked.connect(self.open_component_details)

    def get_searched_component(self):
        if self.searchbar.text() not in self.all_components_display:
            return
        for i in range(self.table.rowCount()):
            for j in range(self.table.columnCount()):
                if self.table.item(
                        i, 0).background().color() != QtGui.QColor("orange"):
                    if self.table.item(
                            i,
                            0).background().color() != QtGui.QColor("yellow"):
                        self.table.item(i,
                                        j).setBackground(QtGui.QColor("white"))

        found_item_list = self.table.findItems(self.searchbar.text(),
                                               QtCore.Qt.MatchExactly)
        found_item = found_item_list[0]
        self.table.scrollToItem(found_item,
                                QtWidgets.QAbstractItemView.PositionAtTop)
        utils.give_light_blue_color_to_found_item_row(self.table, found_item)

    def export_to_spreadsheet(self):
        from pandas import DataFrame, ExcelWriter
        from datetime import datetime

        num_rows = self.table.rowCount()
        num_cols = self.table.columnCount()
        df = DataFrame(columns=self.main_section_header_labels,
                       index=range(num_rows))
        for i in range(num_rows):
            for j in range(num_cols):
                df.iloc[(i, j)] = self.table.item(i, j).text()

        date = datetime.now().strftime("%d-%m-%Y")
        filepath_and_name = f"output\\RESUMEN DE STOCK {date}.xlsx"
        writer = ExcelWriter(filepath_and_name)
        df.to_excel(writer, "Hoja1", index=False)
        writer.sheets["Hoja1"].column_dimensions["A"].width = 30
        writer.save()
        os.startfile(filepath_and_name)

        statusbar = self.parent().parent().statusbar
        statusbar.show_quick_message("Resumen exportado")

    def sort_components_alphabetically(self, logical_index):
        if logical_index == 0:
            self.table.setSortingEnabled(True)
            self.table.horizontalHeader().setSortIndicatorShown(False)
        if logical_index != 0:
            self.table.setSortingEnabled(False)

    def open_component_details(self, row, col):
        if col == 0:
            self.selected_comp_display = self.table.item(row, col).text()
            db = db_manager.DB_Manager()
            self.selected_comp_SQL = db.get_SQL_name_for_component(
                self.selected_comp_display)
            db.close_connection()
        ComponentDetailsDialog(self).exec_()
class ProductionReport(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(ProductionReport, self).__init__(parent)
        self.setWindowFlags(
            QtCore.Qt.Dialog
            | QtCore.Qt.CustomizeWindowHint
            | QtCore.Qt.WindowCloseButtonHint
        )
        self.setFixedWidth(410)

        self.entered_products_and_amounts = {}
        self.needed_comps_and_amounts = {}

        title = QtWidgets.QLabel("Informe de producción")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        code_label = QtWidgets.QLabel("Código:")
        self.code_field = AutocapField("K12345...")

        code_regex = QtCore.QRegExp("^[KBTkbt]{1}[0-9]{1,7}")
        code_validator = QtGui.QRegExpValidator(code_regex, self.code_field)

        self.code_field.setValidator(code_validator)
        self.code_field.setFixedWidth(110)
        self.code_field.setFocus()

        code_section = QtWidgets.QHBoxLayout()
        code_section.addStretch()
        code_section.addWidget(code_label)
        code_section.addWidget(self.code_field)
        code_section.addStretch()

        groupbox = QtWidgets.QGroupBox("Productos a fabricar")
        groupbox.setStyleSheet(generic_groupbox_normal_style)
        groupbox.setMinimumWidth(252)

        self.add_button = QtWidgets.QPushButton("+ Agregar producto")
        self.add_button.setShortcut("Alt+a")
        self.products_holder_section = QtWidgets.QVBoxLayout()

        groupbox_inner_section = QtWidgets.QVBoxLayout()
        groupbox_inner_section_1 = QtWidgets.QHBoxLayout()
        groupbox_inner_section_1.addWidget(self.add_button)
        groupbox_inner_section_2 = QtWidgets.QHBoxLayout()
        groupbox_inner_section_2.addLayout(self.products_holder_section)
        groupbox_inner_section.addLayout(groupbox_inner_section_1)
        groupbox_inner_section.addLayout(groupbox_inner_section_2)
        groupbox.setLayout(groupbox_inner_section)
        groupbox_section = QtWidgets.QHBoxLayout()
        groupbox_section.addStretch()
        groupbox_section.addWidget(groupbox)
        groupbox_section.addStretch()

        self.execute_button = QtWidgets.QPushButton("Calcular »")
        self.execute_button.setShortcut("Alt+c")
        self.execute_button.setFixedWidth(150)

        self.back_button = QtWidgets.QPushButton("« Volver")
        self.back_button.setShortcut("Alt+v")
        self.back_button.setFixedWidth(150)

        self.bottom_section = QtWidgets.QHBoxLayout()
        self.bottom_section.addWidget(self.back_button)
        self.bottom_section.addWidget(self.execute_button)

        self.layout = QtWidgets.QVBoxLayout()
        self.layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        self.layout.addWidget(title)
        self.layout.addLayout(code_section)
        self.layout.addLayout(groupbox_section)
        self.layout.addLayout(self.bottom_section)

        self.setLayout(self.layout)

        self.add_button.clicked.connect(self.add_line_item)
        self.back_button.clicked.connect(self.close)
        self.execute_button.clicked.connect(self.on_execute_clicked)

    def add_line_item(self):
        product_field = AutocapField("Producto...")
        product_field.setFixedWidth(120)
        product_field.set_completer(source="recipes")
        product_field.setFocus()

        value_field = StockNumberField("Cantidad...")
        value_field.setFixedWidth(80)

        close_button = LineItemCloseButton(holder=self.products_holder_section)

        single_line_section = QtWidgets.QHBoxLayout()
        single_line_section.addWidget(product_field)
        single_line_section.addWidget(value_field)
        single_line_section.addWidget(close_button)
        self.products_holder_section.addLayout(single_line_section)

    def on_execute_clicked(self):
        if self.execute_button.text() == "Calcular »":
            if self.test_if_there_are_no_products():
                return
            if self.test_if_there_are_duplicates():
                return
            if self.test_if_there_are_unrecognized_products():
                return
            self.preview_calculation()
        elif self.execute_button.text() == "Generar informe »":
            if self.test_if_code_missing():
                return
            self.generate_production_report()

    def test_if_there_are_no_products(self):
        no_line_items = not self.products_holder_section.children()
        contents = utils.get_line_items_contents(self.products_holder_section)
        empty_string = tests.test_if_empty_string_in_line_items_contents(contents)
        if no_line_items or empty_string:
            WarningBox(
                "Sin productos", "Completar o borrar campos\nvacíos antes de ejecutar."
            ).exec_()
            return True
        else:
            return False

    def test_if_there_are_duplicates(self):
        contents = utils.get_line_items_contents(self.products_holder_section)
        duplicates = tests.test_if_duplicated_first_value_in_line_items_contents(
            contents
        )
        if duplicates:
            WarningBox(
                "Componentes duplicados", "Borrar uno de los componentes duplicados."
            ).exec_()
            return True
        else:
            return False

    def test_if_there_are_unrecognized_products(self):
        contents = utils.get_line_items_contents(self.products_holder_section)
        products = contents[0::2]
        db = db_manager.DB_Manager()
        existing_recipes = db.get_all_recipes_as_display()
        db.close_connection()
        unrecognized_products = not set(products).issubset(existing_recipes)
        if unrecognized_products:
            WarningBox(
                "Componente extraño",
                "Componente no reconocido. Cargar el\ncomponente desde el autocompletado.",
            ).exec_()
            return True
        else:
            return False

    def test_if_code_missing(self):
        code_missing = self.code_field.text() == ""
        if code_missing:
            WarningBox("Código faltante", "Ingresar código\nantes de generar.").exec_()
            return True
        else:
            return False

    def preview_calculation(self):
        table = QtWidgets.QTableWidget()
        table.setFixedWidth(360)
        table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        table.verticalHeader().setVisible(False)
        table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        table.setFocusPolicy(QtCore.Qt.NoFocus)
        table.setColumnCount(2)
        table.setHorizontalHeaderLabels(["Componente", "Necesidad"])
        table.horizontalHeaderItem(0).setTextAlignment(QtCore.Qt.AlignHCenter)
        table.horizontalHeaderItem(1).setTextAlignment(QtCore.Qt.AlignHCenter)
        table.horizontalHeader().setDefaultSectionSize(70)
        table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
        table.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.Fixed)
        table_section = QtWidgets.QVBoxLayout()
        table_section.addWidget(table)

        self.layout.addLayout(table_section)

        self.add_button.setEnabled(False)

        utils.delete_layout(self.bottom_section)

        self.back_button = QtWidgets.QPushButton("« Volver")
        self.back_button.setShortcut("Alt+v")

        self.execute_button = QtWidgets.QPushButton("Calcular »")
        self.execute_button.setShortcut("Alt+c")

        self.bottom_section = QtWidgets.QHBoxLayout()
        self.bottom_section.addWidget(self.back_button)
        self.bottom_section.addWidget(self.execute_button)

        self.back_button.clicked.connect(self.close)
        self.add_button.clicked.connect(self.add_line_item)
        self.execute_button.clicked.connect(self.on_execute_clicked)

        self.layout.addLayout(self.bottom_section)

        self.entered_products_and_amounts = utils.get_line_items_contents(
            self.products_holder_section, as_dictionary=True
        )

        series_for_production = []

        db = db_manager.DB_Manager()

        for (
            product_to_be_manufactured,
            amount_to_be_manufactured,
        ) in self.entered_products_and_amounts.items():
            recipe_sql = utils.format_display_name_into_sql_name(
                product_to_be_manufactured
            )
            product_recipe = db.get_recipe_contents(recipe_sql)
            for comp_name, comp_amount in product_recipe.items():
                product_recipe[comp_name] = comp_amount * amount_to_be_manufactured

            series_for_production.append(product_recipe)

        db.close_connection()

        dd = defaultdict(list)

        for single_recipe in series_for_production:
            for component, amount in single_recipe.items():
                dd[component].append(amount)

        for key, value in dd.items():
            for _ in value:
                dd[key] = sum(value)

        self.needed_comps_and_amounts = dict(dd)

        table.setRowCount(len(self.needed_comps_and_amounts))

        utils.populate_table_column_with_list_of_strings(
            table=table, col_num=0, input_list=self.needed_comps_and_amounts.keys()
        )

        utils.populate_table_column_with_list_of_integers(
            table=table, col_num=1, input_list=self.needed_comps_and_amounts.values()
        )

        custom_height = table.rowCount() * 30 + 25
        if table.rowCount() <= 3:
            table.setMaximumHeight(custom_height)
            table.setFixedHeight(custom_height)
        elif table.rowCount() > 4:
            table.setMaximumHeight(205)
            table.setFixedHeight(205)

        self.execute_button.setText("Generar informe »")
        self.execute_button.setShortcut("Alt+g")

        self.code_field.setFocus()

        for l in self.products_holder_section.children():
            l.itemAt(0).widget().setDisabled(True)
            l.itemAt(1).widget().setDisabled(True)

        self.add_button.clicked.disconnect()

    def generate_production_report(self):
        code = self.code_field.text()
        path = os.getcwd() + "\\src\\main\\resources\\production_report_template.xlsx"
        wb = load_workbook(path)
        ws = wb["Informe"]
        for product_name, product_amount in self.entered_products_and_amounts.items():
            for cell in ws["B"][3:]:
                if cell.value is None:
                    cell.value = product_name
                    break

            for cell in ws["C"][3:]:
                if cell.value is None:
                    cell.value = utils.format_number_for_display(product_amount)
                    break

        db = db_manager.DB_Manager()
        df = db.make_needs_and_stocks_df(self.needed_comps_and_amounts)
        db.close_connection()
        assembler = code[0]
        fmt = utils.format_number_for_display
        for i in range(len(df)):
            for cell in ws["D"][3:]:
                if cell.value is None:
                    cell.value = df["comp"][i]
                    break

            for cell in ws["E"]:
                if cell.value is None:
                    cell.value = fmt(df["need"][i])
                    break

            for cell in ws["F"]:
                if cell.value is None:
                    if df["need"][i] <= df[assembler][i] + df["V"][i]:
                        cell.value = "Sí"
                    else:
                        diff = fmt(df["need"][i] - (df[assembler][i] + df["V"][i]))
                        cell.value = f"No, faltan {diff} unidades."
                    break

            for cell in ws["G"]:
                if cell.value is None:
                    cell.value = fmt(max(0, df["need"][i] - df[assembler][i]))
                    break

            for cell in ws["H"]:
                if cell.value is None:
                    cell.value = "0"
                    break

        ws["B2"] = code
        ws["F2"] = datetime.now().strftime("%d/%m/%Y")
        if code.startswith("K"):
            ws["H2"] = "Karina"
        elif code.startswith("B"):
            ws["H2"] = "Brid"
        elif code.startswith("T"):
            ws["H2"] = "Tercero"
        current_date_hyphens = datetime.now().strftime("%d-%m-%Y")
        filepath_and_name = (
            f"output\\INFORME DE PRODUCCIÓN {code} {current_date_hyphens}.xlsx"
        )
        wb.save(filepath_and_name)
        wb.close()
        os.startfile(
            f"output\\INFORME DE PRODUCCIÓN {code} {current_date_hyphens}.xlsx"
        )

        self.close()
Ejemplo n.º 8
0
class DeleteRecipeDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(DeleteRecipeDialog, self).__init__(parent)
        self.recipe_being_deleted_display = ""
        self.recipe_being_deleted_sql = ""
        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)
        self.setFixedWidth(200)
        self.setFixedHeight(250)

        title = QtWidgets.QLabel("Borrar receta")
        title.setAlignment(QtCore.Qt.AlignCenter)
        title.setStyleSheet(generic_title_style)

        self.searchbar = AutocapField("Buscar receta a borrar...")
        self.searchbar.set_completer(source="recipes")

        self.table = QtWidgets.QTableWidget()
        self.table.setFocusPolicy(QtCore.Qt.NoFocus)
        self.table.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table.verticalHeader().setVisible(False)
        self.table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
        self.table.setColumnCount(1)
        self.table.setHorizontalHeaderLabels(["Producto"])
        self.table.horizontalHeaderItem(0).setTextAlignment(
            QtCore.Qt.AlignHCenter)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QtWidgets.QHeaderView.Stretch)

        db = db_manager.DB_Manager()
        self.all_recipes_display = db.get_all_recipes_as_display()
        db.close_connection()

        self.table.setRowCount(len(self.all_recipes_display))
        utils.populate_table_column_with_list_of_strings(
            table=self.table, col_num=0, input_list=self.all_recipes_display)

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(self.searchbar)
        layout.addWidget(self.table)
        layout.addWidget(back_button)

        self.setLayout(layout)

        back_button.clicked.connect(self.close)
        self.searchbar.returnPressed.connect(self.on_searchbar_return_pressed)
        self.table.cellDoubleClicked.connect(self.on_table_item_double_clicked)

        if not self.all_recipes_display:
            InformationBox("Sin recetas",
                           "No hay recetas para borrar.").exec_()
            QtCore.QTimer.singleShot(1, self.close)

    def on_searchbar_return_pressed(self):
        if self.searchbar.text() not in self.all_recipes_display:
            return
        utils.scroll_to_row_in_table(self.table, self.searchbar.text())
        self.recipe_being_deleted_display = self.searchbar.text()
        self.delete_recipe_from_db()

    def on_table_item_double_clicked(self, row, col):
        self.recipe_being_deleted_display = self.table.item(row, col).text()
        self.delete_recipe_from_db()

    def delete_recipe_from_db(self):
        self.recipe_being_deleted_sql = utils.format_display_name_into_sql_name(
            self.recipe_being_deleted_display)
        box = QuestionBox(
            "Confirmación",
            f"¿Borrar receta {self.recipe_being_deleted_display}?")
        box.exec_()

        if box.clickedButton() == box.button(QtWidgets.QMessageBox.No):
            pass
        elif box.clickedButton() == box.button(QtWidgets.QMessageBox.Yes):
            db = db_manager.DB_Manager()
            db.delete_recipe(self.recipe_being_deleted_sql)
            db.log_new_config_record(config="Borrado de receta",
                                     details=self.recipe_being_deleted_display)
            db.close_connection()
            admin_window = self.parent().parent().parent()
            admin_window.statusbar.show_quick_message(
                "Receta borrada: " + self.recipe_being_deleted_display)
            admin_window.start_screen.rebuild_main_section()

            self.close()
Ejemplo n.º 9
0
class MovementsDialog(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(MovementsDialog, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Dialog
                            | QtCore.Qt.CustomizeWindowHint
                            | QtCore.Qt.WindowCloseButtonHint)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        self.setFixedWidth(800)
        self.setFixedHeight(403)

        self.df = ""

        self.title = QtWidgets.QLabel("Historial de movimientos")
        self.title.setStyleSheet(movements_dialog_title_style)
        self.title.setAlignment(QtCore.Qt.AlignCenter)

        self.groupbox = QtWidgets.QGroupBox("Filtros")
        self.groupbox.setStyleSheet(generic_groupbox_normal_style)
        self.groupbox.setMinimumWidth(400)

        self.date_button = QtWidgets.QPushButton("Período")
        self.date_button.setMaximumHeight(22)
        self.date_button.setFocusPolicy(QtCore.Qt.NoFocus)

        self.mov_combobox = QtWidgets.QComboBox()
        self.mov_combobox.addItem("Movimiento")
        self.mov_combobox.addItem("Ingreso")
        self.mov_combobox.addItem("Egreso")
        self.mov_combobox.setFixedWidth(85)

        self.comp_field = AutocapField("Componente...")
        self.comp_field.setFixedWidth(300)
        self.comp_field.set_completer(source="comps in movements")
        self.comp_field.setFocus()
        self.dest_combobox = QtWidgets.QComboBox()
        self.dest_combobox.addItem("Destino")

        destinations = ["Depósito", "Karina", "Brid", "Tercero", "Uso interno"]

        for destination in destinations:
            self.dest_combobox.addItem(destination)

        self.user_combobox = QtWidgets.QComboBox()
        self.user_combobox.addItem("Usuario")

        self.db = db_manager.DB_Manager()

        users = self.db.get_all_admin_users()
        for user in users:
            self.user_combobox.addItem(user)

        self.user_combobox.setFixedWidth(100)

        filters_layout = QtWidgets.QHBoxLayout()
        filters_layout.addWidget(self.date_button)
        filters_layout.addWidget(self.mov_combobox)
        filters_layout.addWidget(self.comp_field)
        filters_layout.addWidget(self.dest_combobox)
        filters_layout.addWidget(self.user_combobox)

        groupbox_inner_section = QtWidgets.QVBoxLayout()
        groupbox_inner_section.addLayout(filters_layout)
        self.groupbox.setLayout(groupbox_inner_section)
        groupbox_section = QtWidgets.QHBoxLayout()
        groupbox_section.addStretch()
        groupbox_section.addWidget(self.groupbox)
        groupbox_section.addStretch()

        back_button = QtWidgets.QPushButton("« Volver")
        back_button.setShortcut("Alt+v")
        back_button.setFocusPolicy(QtCore.Qt.NoFocus)

        self.delete_button = QtWidgets.QPushButton("× Borrar historial")
        self.delete_button.setShortcut("Alt+b")
        self.delete_button.setFocusPolicy(QtCore.Qt.NoFocus)

        self.export_button = QtWidgets.QPushButton("Exportar historial »")
        self.export_button.setShortcut("Alt+x")
        self.export_button.setFocusPolicy(QtCore.Qt.NoFocus)

        bottom_section = QtWidgets.QHBoxLayout()
        bottom_section.addWidget(back_button)
        bottom_section.addWidget(self.delete_button)
        bottom_section.addWidget(self.export_button)

        table_layout = QtWidgets.QVBoxLayout()

        self.table_view = QtWidgets.QTableView()
        self.table_view.verticalHeader().setVisible(False)

        table_layout.addWidget(self.table_view)
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.title)
        layout.addLayout(groupbox_section)
        layout.addLayout(table_layout)
        layout.addLayout(bottom_section)

        self.setLayout(layout)

        self.build_table_view()

        back_button.clicked.connect(self.close)
        self.delete_button.clicked.connect(self.delete_movements)
        self.export_button.clicked.connect(self.export_to_spreadsheet)
        self.date_button.clicked.connect(self.create_date_selection_subdialog)
        self.comp_field.returnPressed.connect(self.on_comp_field_return_press)
        self.mov_combobox.currentIndexChanged.connect(self.on_combobox_change)
        self.dest_combobox.currentIndexChanged.connect(self.on_combobox_change)
        self.user_combobox.currentIndexChanged.connect(self.on_combobox_change)

    def create_date_selection_subdialog(self):
        self.date_selection_subdialog = DateSelectionSubdialog(self)
        self.date_selection_subdialog.exec_()

    def build_table_view(self):
        self.df = self.db.get_movements_as_dataframe()
        self.db.close_connection()

        widgets = [
            self.delete_button,
            self.export_button,
            self.date_button,
            self.mov_combobox,
            self.dest_combobox,
            self.user_combobox,
            self.comp_field,
        ]
        if self.df.empty:
            for i in widgets:
                i.setDisabled(True)
            return

        row_count = len(self.df.index)
        col_count = len(self.df.columns)

        self.model = QtGui.QStandardItemModel(row_count, col_count)
        self.model.setHorizontalHeaderLabels(self.df.columns)
        self.table_view.setModel(self.model)

        for count, df_col_name in enumerate(self.df):
            utils.populate_model_column_with_list_of_items(
                model=self.model,
                col_num=count,
                input_list=self.df[df_col_name])

        text_and_color = {
            "Ingreso": QtGui.QColor("#a3be8c"),
            "Egreso": QtGui.QColor("#ff91a4"),
        }

        for text, color in text_and_color.items():
            for x in range(self.model.rowCount()):
                for y in range(self.model.columnCount()):
                    if self.model.item(x, 2).text() == text:
                        self.model.item(x, y).setBackground(color)

        self.table_view.setColumnWidth(0, 95)
        self.table_view.setColumnWidth(1, 65)
        self.table_view.horizontalHeader().setSectionResizeMode(
            3, QtWidgets.QHeaderView.Stretch)
        self.table_view.setColumnWidth(2, 90)
        self.table_view.setColumnWidth(4, 80)
        self.table_view.setColumnWidth(5, 120)
        self.table_view.setColumnWidth(6, 100)
        self.table_view.setSelectionMode(
            QtWidgets.QAbstractItemView.NoSelection)
        self.table_view.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.table_view.setFocusPolicy(QtCore.Qt.NoFocus)
        self.table_view.setStyleSheet(movements_dialog_table_view_style)

    def clear_all_filters(self):
        self.date_button.setText("Período")
        self.comp_field.clear()
        self.mov_combobox.setCurrentIndex(0)
        self.dest_combobox.setCurrentIndex(0)
        self.user_combobox.setCurrentIndex(0)
        self.table_view.setModel(self.model)
        self.groupbox.setTitle("Filtros")
        self.groupbox.setStyleSheet(generic_groupbox_normal_style)

    def clear_all_filters_except(self, chosen_filter):
        comboboxes = [
            self.mov_combobox, self.dest_combobox, self.user_combobox
        ]

        if isinstance(chosen_filter, QtWidgets.QComboBox):
            self.date_button.setText("Período")
            self.comp_field.clear()
            for i in comboboxes:
                if i != chosen_filter:
                    i.setCurrentIndex(0)
        elif isinstance(chosen_filter, QtWidgets.QLineEdit):
            self.date_button.setText("Período")
            for i in comboboxes:
                i.setCurrentIndex(0)
        elif isinstance(chosen_filter, QtWidgets.QPushButton):
            self.comp_field.clear()
            for i in comboboxes:
                i.setCurrentIndex(0)

    def apply_filter_based_on_item(self, chosen_filter, chosen_item):
        filter_proxy_model = self.get_filter_proxy_model(chosen_filter)
        filter_proxy_model.setSourceModel(self.model)
        filter_proxy_model.setFilterFixedString(chosen_item)
        self.table_view.setModel(filter_proxy_model)
        self.groupbox.setTitle("Filtro activado")
        self.groupbox.setStyleSheet(
            movements_dialog_groupbox_filter_selected_style)

    def get_filter_proxy_model(self, chosen_filter):
        filter_proxy_model = QtCore.QSortFilterProxyModel()
        if chosen_filter in ("Movimiento", "Destino", "Usuario"):
            filter_and_column = {"Movimiento": 2, "Destino": 5, "Usuario": 6}
            filter_proxy_model.setFilterKeyColumn(
                filter_and_column[chosen_filter])
        elif chosen_filter == "Componente":
            filter_proxy_model.setFilterRegExp(
                QtCore.QRegExp(self.comp_field.text()))
            filter_proxy_model.setFilterKeyColumn(3)
        return filter_proxy_model

    def on_combobox_change(self):
        combobox = self.sender()
        chosen_filter = combobox.itemText(0)
        chosen_item = combobox.currentText()
        self.clear_all_filters_except(combobox)
        if chosen_item in ("Movimiento", "Destino", "Usuario"):
            self.clear_all_filters()
        else:
            self.apply_filter_based_on_item(chosen_filter, chosen_item)

    def on_comp_field_return_press(self):
        user_input = self.comp_field.text()
        self.clear_all_filters_except(self.comp_field)
        if not user_input:
            self.clear_all_filters()
        elif user_input:
            self.apply_filter_based_on_item("Componente", user_input)

    def on_date_selected(self):
        selected_date = self.date_selection_subdialog.selected_date
        self.date_button.setText(selected_date)
        self.clear_all_filters_except(self.date_button)
        self.apply_filter_based_on_item("Fecha", selected_date)

    def delete_movements(self):
        box = QuestionBox("Confirmación", "¿Borrar historial de movimientos?")
        box.exec_()
        if box.clickedButton() == box.button(QtWidgets.QMessageBox.Yes):
            db = db_manager.DB_Manager()
            db.delete_all_movements()
            db.close_connection()
            self.close()
            statusbar = self.parent().parent().parent().parent().statusbar
            statusbar.show_quick_message("Historial de movimientos borrado")
        elif box.clickedButton() == box.button(QtWidgets.QMessageBox.No):
            pass

    def export_to_spreadsheet(self):
        self.export_button.setText("Esperar...")
        current_date = datetime.now().strftime("%d-%m-%Y")
        filepath_and_name = f"output\\Historial de movimientos {current_date}.xlsx"
        writer = ExcelWriter(filepath_and_name)
        self.df.to_excel(writer, "Hoja1", index=False)
        writer.sheets["Hoja1"].column_dimensions["A"].width = 13
        writer.sheets["Hoja1"].column_dimensions["B"].width = 8
        writer.sheets["Hoja1"].column_dimensions["C"].width = 15
        writer.sheets["Hoja1"].column_dimensions["D"].width = 30
        writer.sheets["Hoja1"].column_dimensions["E"].width = 10
        writer.sheets["Hoja1"].column_dimensions["F"].width = 15
        writer.sheets["Hoja1"].column_dimensions["G"].width = 15
        writer.save()
        os.startfile(filepath_and_name)

        self.export_button.setText("Exportar historial »")

        self.close()

        statusbar = self.parent().parent().parent().parent().statusbar
        statusbar.show_quick_message("Historial de movimientos exportado")