Esempio n. 1
0
 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 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 add_recipe_item_line(self):
        searchbar_recipe_component = AutocapField("Componente...")
        searchbar_recipe_component.setFixedWidth(130)

        searchbar_recipe_component.set_completer(source="comps in stock")
        searchbar_recipe_amount = StockNumberField("Cantidad...")
        searchbar_recipe_amount.setFixedWidth(85)

        close_button = QtWidgets.QPushButton("×")
        close_button.setFixedWidth(20)
        close_button.clicked.connect(self.remove_recipe_item_via_close_button)

        recipe_item_line_layout = QtWidgets.QHBoxLayout()
        recipe_item_line_layout.addWidget(searchbar_recipe_component)
        recipe_item_line_layout.addWidget(searchbar_recipe_amount)
        recipe_item_line_layout.addWidget(close_button)

        self.comps_holder_section.addLayout(recipe_item_line_layout)
Esempio n. 4
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_()
Esempio n. 5
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_()
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_()
Esempio n. 7
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_()
Esempio 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()
Esempio 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")