import pandas as pd from schema.pydantic import settings, Translit import os class BaseHandler: def __init__(self, file_path:str): self.file_name = file_path self.file_path = os.path.join(settings.INPUTDIR, file_path) def struct(self): try: return pd.ExcelFile(self.file_path) except Exception as e: raise Exception(f"⚠️ Ошибка при получении структуры {self.file_path}: {e}") def read(self): try: return pd.read_excel(self.file_path) except Exception as e: raise Exception(f"⚠️ Ошибка при чтении файла {self.file_path}: {e}") class Handler(BaseHandler): def get_articles_with_sales(self, columns:dict, sheet_name:str): xls = self.struct() if sheet_name not in xls.sheet_names: raise Exception('⚠️ Лист {sheet_name} не найден') df = pd.read_excel(xls, sheet_name=sheet_name) df = df.iloc[:, list(columns.values())] df.columns = list(columns.keys()) #Нормализация df['Артикул'] = df['Артикул'].replace(Translit.TRANSLIT, regex=True) #группировка df['Артикул'] = df['Артикул'].astype(str).str.upper().str.extract(f'({settings.PATTERN})') df.dropna(subset=["Артикул"], inplace=True) agg_dict = {col: "sum" for col in df.columns if col != "Артикул" and col != "Наименование"} # по умолчанию суммируем все кроме Артикул if "Наименование" in df.columns: agg_dict["Наименование"] = lambda x: "\n".join(sorted(set(x))) df= df.groupby("Артикул", as_index=False).agg(agg_dict) #Исчисляемые колонки df["Все удержания в %"] = df.apply( lambda row: (row["Все_удержания_магазина"] / row["Выручка"] * 100) if row["Выручка"] != 0 else 0, axis=1 ) if "Выкупы" in df.columns and "Не_выкупы" in df.columns: df["Всего заказано"] = df.apply( lambda row: row["Выкупы"]+row["Не_выкупы"], axis=1 ) df["Процент выкупа"] = df.apply( lambda row: ((row["Выкупы"] - row["Возвраты"]) / row["Всего заказано"] * 100) if row["Всего заказано"] != 0 else 0, axis=1 ) df["Маржинальность"] = df.apply( lambda row: (row["Прибыль"] / row["Выручка"] * 100) if row["Выручка"] != 0 else 0, axis=1 ) df=df.round(2) df = df.sort_values(ascending=False,by="Прибыль") def multi_style(val): if val < 0: return "background-color: red" elif val > 0: return "background-color: green; color: white" return "" styled = df.style.map(multi_style, subset=["Маржинальность","Прибыль"]) styled.to_excel(f"output/{self.file_name}", engine="openpyxl", index=False)