diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e97d5fd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..82fd352 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + { + "associatedIndex": 4 +} + + + + { + "keyToString": { + "ModuleVcsDetector.initialDetectionPerformed": "true", + "Python.main.executor": "Run", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", + "RunOnceActivity.git.unshallow": "true", + "RunOnceActivity.typescript.service.memoryLimit.init": "true", + "ai.playground.ignore.import.keys.banner.in.settings": "true", + "git-widget-placeholder": "main", + "ignore.virus.scanning.warn.message": "true", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "configurable.group.editor", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + + + + + + + + + + + 1775246703281 + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/data/sales.csv b/data/sales.csv new file mode 100644 index 0000000..4f1a4de --- /dev/null +++ b/data/sales.csv @@ -0,0 +1,20 @@ +Ноутбук,Электроника,1200,5,2024-01-15 +Мышь,Электроника,25,15,2024-01-20 +Клавиатура,Электроника,45,10,2024-02-10 +Кофеварка,Техника,150,3,2024-02-15 +Футболка,Одежда,20,50,2024-02-20 +Джинсы,Одежда,60,20,2024-03-05 +Лампа,Дом,35,12,2024-03-12 +Чайник,Техника,80,8,2024-03-20 +Монитор,Электроника,300,4,2024-04-01 +Носки,Одежда,5,100,2024-04-05 +Рюкзак,Аксессуары,55,15,2024-04-10 +Книга,Хобби,15,30,2024-01-25 +Блокнот,Хобби,8,40,2024-02-01 +Ручка,Хобби,2,200,2024-02-05 +Коврик для йоги,Спорт,25,20,2024-03-15 +Гантели,Спорт,40,10,2024-04-12 +Наушники,Электроника,90,12,2024-04-18 +Сковорода,Дом,45,6,2024-01-30 +Подушка,Дом,25,14,2024-02-28 +Зеркало,Дом,110,2,2024-03-25 diff --git a/data/sales.txt b/data/sales.txt new file mode 100644 index 0000000..e69de29 diff --git a/main.py b/main.py new file mode 100644 index 0000000..ec959c9 --- /dev/null +++ b/main.py @@ -0,0 +1,117 @@ +import csv +from collections import defaultdict + + +def load_data(filepath: str) -> list[dict]: + records = [] + with open(filepath, mode='r', encoding='utf-8') as f: + reader = csv.reader(f) + for row in reader: + if not row: continue + name, category, price, quantity, date = row + records.append({ + "name": name.strip(), + "category": category.strip(), + "price": float(price), + "quantity": int(quantity), + "date": date.strip() + }) + return records + + +def clean_data(records: list[dict]) -> list[dict]: + cleaned = [] + for r in records: + if r['price'] >= 0 and r['quantity'] >= 0: + r['category'] = r['category'].lower() + cleaned.append(r) + return cleaned + + +def filter_by_category(records: list[dict], category: str) -> list[dict]: + return [r for r in records if r['category'] == category.lower()] + + +def filter_by_price_range(records: list[dict], min_price: float, max_price: float) -> list[dict]: + return [r for r in records if min_price <= r['price'] <= max_price] + + +def total_revenue(records: list[dict]) -> float: + return sum(r['price'] * r['quantity'] for r in records) + + +def category_revenue(records: list[dict]) -> dict[str, float]: + rev_map = defaultdict(float) + for r in records: + rev_map[r['category']] += r['price'] * r['quantity'] + return dict(rev_map) + + +def top_n_items(records: list[dict], n: int) -> list[tuple[str, int]]: + counts = defaultdict(int) + for r in records: + counts[r['name']] += r['quantity'] + sorted_items = sorted(counts.items(), key=lambda x: x[1], reverse=True) + return sorted_items[:n] + + +def monthly_sales(records: list[dict]) -> dict[str, float]: + monthly_rev = defaultdict(float) + for r in records: + month = r['date'][:7] # Извлекает YYYY-MM + monthly_rev[month] += r['price'] * r['quantity'] + return dict(sorted(monthly_rev.items())) + + +def best_selling_category(records: list[dict]) -> str: + cat_rev = category_revenue(records) + if not cat_rev: return "" + return max(cat_rev, key=cat_rev.get) + + +def export_summary(records: list[dict], output_path: str) -> None: + rev = total_revenue(records) + best_cat = best_selling_category(records) + top3 = top_n_items(records, 3) + monthly = monthly_sales(records) + + with open(output_path, 'w', encoding='utf-8') as f: + f.write("СВОДНЫЙ ОТЧЕТ ПО ПРОДАЖАМ\n") + f.write("=" * 30 + "\n") + f.write(f"Общая выручка: {rev:.2f}\n") + f.write(f"Лучшая категория: {best_cat}\n\n") + f.write("Топ-3 товара (по количеству):\n") + for name, qty in top3: + f.write(f"- {name}: {qty} шт.\n") + f.write("\nВыручка по месяцам:\n") + for month, m_rev in monthly.items(): + f.write(f"- {month}: {m_rev:.2f}\n") + + +def main(): + #Пометки для себя любимого + #Загрузка + data = load_data("data/sales.csv") + #Очистка + data = clean_data(data) + #Фильтрация + filtered = filter_by_price_range(data, 10, 500) + #Анализ + rev = total_revenue(filtered) + cat_rev = category_revenue(filtered) + best_cat = best_selling_category(filtered) + top3 = top_n_items(filtered, 3) + monthly = monthly_sales(filtered) + #Вывод в консоль + print(f"--- Результаты анализа (фильтр: 10-500 руб) ---") + print(f"Общая выручка: {rev:.2f}") + print(f"Лучшая категория: {best_cat.capitalize()}") + print(f"Топ-3 товара: {top3}") + print(f"Выручка по месяцам: {monthly}") + #Экспорт + export_summary(filtered, "report.txt") + print(f"\nОтчет успешно сохранен в report.txt") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/report.txt b/report.txt new file mode 100644 index 0000000..e3a8f60 --- /dev/null +++ b/report.txt @@ -0,0 +1,15 @@ +СВОДНЫЙ ОТЧЕТ ПО ПРОДАЖАМ +============================== +Общая выручка: 9830.00 +Лучшая категория: электроника + +Топ-3 товара (по количеству): +- Футболка: 50 шт. +- Книга: 30 шт. +- Джинсы: 20 шт. + +Выручка по месяцам: +- 2024-01: 1095.00 +- 2024-02: 2250.00 +- 2024-03: 2980.00 +- 2024-04: 3505.00