Привет!

2024-11-09 16:46 | Публичная
import os
import pandas as pd

report_types = {
    'by_retailer': 'Общие продажи по ритейлеру',
    'by_shops': 'Продажи по магазину',
}

# Constants for indices in the filename parts for 'by_retailer' report type
REGION_NAME_INDEX_BY_RETAILER = 0
RETAILER_NAME_INDEX_BY_RETAILER = 1
OFFSET_INDEX_BY_RETAILER = 2
BARCODE_INDEX_BY_RETAILER = 3
SALES_INDEX_BY_RETAILER = 4
SHOPS_INDEX_BY_RETAILER = 5
ALL_SHOPS_INDEX_BY_RETAILER = 6
STOCK_FIRST_INDEX_BY_RETAILER = 7
STOCK_LAST_INDEX_BY_RETAILER = 8
PRICE_PURCH_INDEX_BY_RETAILER = 9
SHELF_PRICE_INDEX_BY_RETAILER = 10
CATEGORY_INDEX_BY_RETAILER = 11

# Constants for indices in the filename parts for 'by_shops' report type
REGION_NAME_INDEX_BY_SHOPS = 0
RETAILER_NAME_INDEX_BY_SHOPS = 1
SHOP_NAME_INDEX_BY_SHOPS = 2
SALES_INDEX_BY_SHOPS = 3
RESIDUAL_INDEX_BY_SHOPS = 4

class ExcelValidator:
    def __init__(self, file_path, report_type):
        """
        Инициализирует ExcelValidator с путем к Excel файлу и типом отчета.

        Args:
        - file_path (str): Путь к Excel файлу для валидации.
        - report_type (str): Тип отчета ('by_retailer' или 'by_shops').
        """
        self.file_path = file_path
        self.data_dict = {}  # Словарь для хранения данных, извлеченных из имени файла
        self.report_type = report_type

        if self.report_type not in report_types:
            raise ValueError(f"Неверный тип отчета: {self.report_type}. Допустимые типы: {list(report_types.keys())}")

    def parse_filename(self, file_name):
        """
        Парсит имя файла и заполняет data_dict извлеченными данными, если формат корректный.

        Args:
        - file_name (str): Имя файла для парсинга.

        Raises:
        - ValueError: Если формат имени файла неверен.
        """
        name_without_extension = os.path.splitext(file_name)[0]
        name_parts = name_without_extension.split('_')

        # Выбираем соответствующие индексы на основе типа отчета
        if self.report_type == 'by_retailer':
            expected_parts = 12  # Настройте при необходимости для 'by_retailer'

            # Проверяем, что в имени файла ожидаемое количество частей
            if len(name_parts) != expected_parts:
                raise ValueError(f"Неверный формат имени файла для '{self.report_type}'. Ожидается {expected_parts} частей, получено {len(name_parts)}.")

            self.data_dict = {
                'region': name_parts[REGION_NAME_INDEX_BY_RETAILER],
                'retailer': name_parts[RETAILER_NAME_INDEX_BY_RETAILER],
                'offset': name_parts[OFFSET_INDEX_BY_RETAILER],
                'barcode': name_parts[BARCODE_INDEX_BY_RETAILER],
                'sales': name_parts[SALES_INDEX_BY_RETAILER],
                'shops': name_parts[SHOPS_INDEX_BY_RETAILER],
                'all_shops': name_parts[ALL_SHOPS_INDEX_BY_RETAILER],
                'stock_first': name_parts[STOCK_FIRST_INDEX_BY_RETAILER],
                'stock_last': name_parts[STOCK_LAST_INDEX_BY_RETAILER],
                'price_purch': name_parts[PRICE_PURCH_INDEX_BY_RETAILER],
                'shelf_price': name_parts[SHELF_PRICE_INDEX_BY_RETAILER],
                'category': name_parts[CATEGORY_INDEX_BY_RETAILER],
            }

        elif self.report_type == 'by_shops':
            expected_parts = 5  # Настройте при необходимости для 'by_shops'

            # Проверяем, что в имени файла ожидаемое количество частей
            if len(name_parts) != expected_parts:
                raise ValueError(f"Неверный формат имени файла для '{self.report_type}'. Ожидается {expected_parts} частей, получено {len(name_parts)}.")

            self.data_dict = {
                'region': name_parts[REGION_NAME_INDEX_BY_SHOPS],
                'retailer': name_parts[RETAILER_NAME_INDEX_BY_SHOPS],
                'shop_name': name_parts[SHOP_NAME_INDEX_BY_SHOPS],
                'sales': name_parts[SALES_INDEX_BY_SHOPS],
                'residual': name_parts[RESIDUAL_INDEX_BY_SHOPS],
            }
        else:
            raise ValueError(f"Неизвестный тип отчета: {self.report_type}")

    def validate_excel_file(self):
        """
        Валидирует Excel файл по указанному пути.

        Raises:
        - FileNotFoundError: Если файл не найден.
        - ValueError: Если файл не является Excel файлом.
        - Exception: Если чтение Excel файла не удалось.
        """
        if not os.path.isfile(self.file_path):
            raise FileNotFoundError(f"Файл не найден по указанному пути: {self.file_path}")

        file_name = os.path.basename(self.file_path)

        # Проверяем, что файл является Excel файлом по расширению
        if not file_name.endswith(('.xls', '.xlsx', '.xlsm')):
            raise ValueError("Файл не является Excel файлом. Пожалуйста, предоставьте файл с расширением .xls, .xlsx или .xlsm.")

        # Парсим имя файла
        self.parse_filename(file_name)

        # Читаем Excel файл с помощью pandas
        try:
            df = pd.read_excel(self.file_path)
            # Здесь можно добавить дополнительную валидацию DataFrame
        except Exception as e:
            raise Exception(f"Ошибка при чтении Excel файла: {e}")

# Пример использования
if __name__ == '__main__':
    # Для отчета 'by_retailer'
    file_path_retailer = 'TEST_Tesco_5_1_2_3_500_0_0_0_0_4.xls'  # Замените на ваш фактический путь к файлу
    validator_retailer = ExcelValidator(file_path_retailer, report_type='by_retailer')
    try:
        validator_retailer.validate_excel_file()
        print("Файл успешно валидирован.")
        print("Data dictionary:", validator_retailer.data_dict)
    except Exception as e:
        print(f"Ошибка при валидации файла: {e}")
Вернуться ко Всем Вставкам
Открыть чат
Чат с Send-Code AI Закрыть чат