Анализ продаж интернет-магазина электроники
This commit is contained in:
commit
9325d8a60e
7
data/sales.json
Normal file
7
data/sales.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{"id": 1, "category": "Смартфоны", "product": "iPhone 15", "price": 120000.0, "quantity": 2, "date": "2026-04-01"},
|
||||||
|
{"id": 2, "category": "Ноутбуки", "product": "MacBook Air M2", "price": 150000.0, "quantity": 1, "date": "2026-04-01"},
|
||||||
|
{"id": 3, "category": "Смартфоны", "product": "Samsung Galaxy S24", "price": 110000.0, "quantity": 3, "date": "2026-04-02"},
|
||||||
|
{"id": 4, "category": "Аксессуары", "product": "AirPods Pro", "price": 25000.0, "quantity": 5, "date": "2026-04-02"},
|
||||||
|
{"id": 5, "category": "Смартфоны", "product": "Xiaomi 14", "price": 80000.0, "quantity": 2, "date": "2026-04-03"}
|
||||||
|
]
|
||||||
35
src/main.py
Normal file
35
src/main.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from sales_analyzer import *
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sales_file_path = "data/sales.json"
|
||||||
|
report_output_path = "sales_report.json"
|
||||||
|
today_str = datetime.now().strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
all_sales = load_sales(sales_file_path)
|
||||||
|
if not all_sales:
|
||||||
|
all_sales = []
|
||||||
|
|
||||||
|
|
||||||
|
all_sales = add_sale(all_sales, "Аксессуары", "Беспроводная мышь", 3500.0, 4, today_str)
|
||||||
|
print(f"Добавлена новая продажа: {all_sales[-1]}")
|
||||||
|
|
||||||
|
|
||||||
|
todays_sales = filter_by_date(all_sales, today_str)
|
||||||
|
print(f"\nПродажи за {today_str}: {len(todays_sales)} записей.")
|
||||||
|
|
||||||
|
|
||||||
|
total_revenue = calculate_revenue(all_sales)
|
||||||
|
top_category = get_top_category(all_sales)
|
||||||
|
average_price = get_average_price(all_sales)
|
||||||
|
best_selling_product = find_best_selling_product(all_sales)
|
||||||
|
|
||||||
|
|
||||||
|
generate_sales_report(all_sales, report_output_path)
|
||||||
|
|
||||||
|
|
||||||
|
print("\n--- Обзор продаж ---")
|
||||||
|
print(f"Общая выручка: {total_revenue:.2f} руб.")
|
||||||
|
print(f"Категория с наибольшей выручкой: {top_category}")
|
||||||
|
print(f"Лучший товар: {best_selling_product['product']} ({best_selling_product['quantity']} шт.)")
|
||||||
|
print(f"Средняя цена товара: {average_price:.2f} руб.")
|
||||||
110
src/sales_analyzer.py
Normal file
110
src/sales_analyzer.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import json
|
||||||
|
from collections import defaultdict
|
||||||
|
def load_sales(file_path: str) -> list:
|
||||||
|
"""Читает JSON из файла и возвращает список продаж."""
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Ошибка: файл {file_path} не найден.")
|
||||||
|
return []
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"Ошибка: некорректный формат JSON в файле {file_path}.")
|
||||||
|
return []
|
||||||
|
def calculate_revenue(sales: list) -> float:
|
||||||
|
"""Вычисляет общую выручку."""
|
||||||
|
total_revenue = 0
|
||||||
|
for sale in sales:
|
||||||
|
revenue = sale.get('price', 0) * sale.get('quantity', 0)
|
||||||
|
total_revenue += revenue
|
||||||
|
return total_revenue
|
||||||
|
def get_top_category(sales: list) -> str:
|
||||||
|
"""Определяет категорию с наибольшей выручкой."""
|
||||||
|
category_revenue = defaultdict(float)
|
||||||
|
for sale in sales:
|
||||||
|
revenue = sale.get('price', 0) * sale.get('quantity', 0)
|
||||||
|
category_revenue[sale.get('category', 'Unknown')] += revenue
|
||||||
|
if not category_revenue:
|
||||||
|
return "Нет данных"
|
||||||
|
return max(category_revenue, key=category_revenue.get)
|
||||||
|
def filter_by_date(sales: list, date: str) -> list:
|
||||||
|
"""Возвращает продажи за указанную дату."""
|
||||||
|
result = []
|
||||||
|
for sale in sales:
|
||||||
|
if sale.get('date') == date:
|
||||||
|
result.append(sale)
|
||||||
|
return result
|
||||||
|
def get_average_price(sales: list) -> float:
|
||||||
|
"""Вычисляет среднюю цену товара."""
|
||||||
|
try:
|
||||||
|
return sum(sale.get('price', 0) for sale in sales) / len(sales)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
return 0.0
|
||||||
|
def find_best_selling_product(sales: list) -> dict:
|
||||||
|
"""Находит товар с максимальным количеством проданных единиц."""
|
||||||
|
product_quantity = defaultdict(int)
|
||||||
|
for sale in sales:
|
||||||
|
product_name = sale.get('product')
|
||||||
|
quantity = sale.get('quantity')
|
||||||
|
if product_name and isinstance(quantity, (int, float)) and quantity > 0:
|
||||||
|
product_quantity[product_name] += quantity
|
||||||
|
if not product_quantity:
|
||||||
|
return {"product": "Нет данных", "quantity": 0}
|
||||||
|
best_product_name = max(product_quantity, key=product_quantity.get)
|
||||||
|
return {"product": best_product_name, "quantity": product_quantity[best_product_name]}
|
||||||
|
|
||||||
|
def count_products_by_category(sales: list) -> dict:
|
||||||
|
"""Подсчитывает количество уникальных товаров в каждой категории."""
|
||||||
|
result = {}
|
||||||
|
for sale in sales:
|
||||||
|
category = sale.get('category', 'Unknown')
|
||||||
|
product = sale.get('product', 'Unknown Product')
|
||||||
|
if category not in result:
|
||||||
|
result[category] = []
|
||||||
|
if product not in result[category]:
|
||||||
|
result[category].append(product)
|
||||||
|
return {cat: len(prods) for cat, prods in result.items()}
|
||||||
|
def get_daily_sales_stats(sales: list) -> dict:
|
||||||
|
"""Возвращает словарь с датами и общей выручкой за каждый день."""
|
||||||
|
daily_revenue = {}
|
||||||
|
for sale in sales:
|
||||||
|
revenue = sale.get('price', 0) * sale.get('quantity', 0)
|
||||||
|
date = sale.get('date', 'Unknown Date')
|
||||||
|
daily_revenue[date] = daily_revenue.get(date, 0) + revenue
|
||||||
|
return daily_revenue
|
||||||
|
def add_sale(sales: list, category: str, product: str, price: float, quantity: int, date: str) -> list:
|
||||||
|
"""Добавляет новую продажу."""
|
||||||
|
new_id = max([sale.get('id', 0) for sale in sales], default=0) + 1
|
||||||
|
new_sale = {
|
||||||
|
"id": new_id,
|
||||||
|
"category": category,
|
||||||
|
"product": product,
|
||||||
|
"price": price,
|
||||||
|
"quantity": quantity,
|
||||||
|
"date": date
|
||||||
|
}
|
||||||
|
sales.append(new_sale)
|
||||||
|
return sales
|
||||||
|
def generate_sales_report(sales: list, output_file: str) -> None:
|
||||||
|
"""Формирует и сохраняет отчёт в файл."""
|
||||||
|
total_revenue = calculate_revenue(sales)
|
||||||
|
top_category = get_top_category(sales)
|
||||||
|
best_selling_product = find_best_selling_product(sales)
|
||||||
|
daily_stats = get_daily_sales_stats(sales)
|
||||||
|
products_by_category = count_products_by_category(sales)
|
||||||
|
average_price = get_average_price(sales)
|
||||||
|
report_data = {
|
||||||
|
"общая выручка": round(total_revenue, 2),
|
||||||
|
"категорию с наибольшими продажами": top_category,
|
||||||
|
"самый продаваемый товар": best_selling_product,
|
||||||
|
"продажи по дням": daily_stats,
|
||||||
|
"количество уникальных товаров": products_by_category,
|
||||||
|
"среднюю цену товара": round(average_price, 2),
|
||||||
|
"число продаж": len(sales)
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
with open(output_file, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(report_data, f, indent=4, ensure_ascii=False)
|
||||||
|
print(f"Отчёт сохранен в файл: {output_file}")
|
||||||
|
except IOError:
|
||||||
|
print(f"Ошибка: не удалось записать в файл {output_file}.")
|
||||||
Loading…
Reference in New Issue
Block a user