finale structure
This commit is contained in:
parent
f4d7e204d7
commit
823a626d38
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Виртуальное окружение
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
|
||||||
|
# Кэш Python
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
|
||||||
|
# Отчёты (генерируются программой)
|
||||||
|
reports/
|
||||||
|
*.txt
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Системные файлы
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
# Бэкапы
|
||||||
|
*.backup
|
||||||
10
.idea/InventoryManager.iml
generated
10
.idea/InventoryManager.iml
generated
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="PYTHON_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Python 3.13 (InventoryManager)" jdkType="Python SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
generated
6
.idea/inspectionProfiles/profiles_settings.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<settings>
|
|
||||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
|
||||||
<version value="1.0" />
|
|
||||||
</settings>
|
|
||||||
</component>
|
|
||||||
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (InventoryManager)" project-jdk-type="Python SDK" />
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/InventoryManager.iml" filepath="$PROJECT_DIR$/.idea/InventoryManager.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
41
.idea/workspace.xml
generated
41
.idea/workspace.xml
generated
@ -1,41 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ChangeListManager">
|
|
||||||
<list default="true" id="b32e6acd-5da1-46f8-a48d-12dc1410b7d6" name="Changes" comment="" />
|
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
||||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectColorInfo"><![CDATA[{
|
|
||||||
"associatedIndex": 3
|
|
||||||
}]]></component>
|
|
||||||
<component name="ProjectId" id="3BrXroiobVyuVOwKhaCCNo1Tl0n" />
|
|
||||||
<component name="ProjectViewState">
|
|
||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
|
||||||
<option name="showLibraryContents" value="true" />
|
|
||||||
</component>
|
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
|
||||||
"keyToString": {
|
|
||||||
"ModuleVcsDetector.initialDetectionPerformed": "true",
|
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true"
|
|
||||||
}
|
|
||||||
}]]></component>
|
|
||||||
<component name="SharedIndexes">
|
|
||||||
<attachedChunks>
|
|
||||||
<set>
|
|
||||||
<option value="bundled-python-sdk-02acdf704d18-cbfc7b97e6b2-com.jetbrains.pycharm.community.sharedIndexes.bundled-PC-252.28539.27" />
|
|
||||||
</set>
|
|
||||||
</attachedChunks>
|
|
||||||
</component>
|
|
||||||
<component name="TaskManager">
|
|
||||||
<task active="true" id="Default" summary="Default task">
|
|
||||||
<changelist id="b32e6acd-5da1-46f8-a48d-12dc1410b7d6" name="Changes" comment="" />
|
|
||||||
<created>1775248363717</created>
|
|
||||||
<option name="number" value="Default" />
|
|
||||||
<option name="presentableId" value="Default" />
|
|
||||||
<updated>1775248363717</updated>
|
|
||||||
</task>
|
|
||||||
<servers />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
ИНВЕНТАРИЗАЦИОННЫЙ ОТЧЁТ
|
|
||||||
==================================================
|
|
||||||
|
|
||||||
Общее количество товаров: 8
|
|
||||||
Общая стоимость склада: 2,750,000.00 руб.
|
|
||||||
|
|
||||||
Топ-3 категории по количеству товаров:
|
|
||||||
1. Электроника: 4 товаров
|
|
||||||
2. Мебель: 2 товаров
|
|
||||||
3. Канцелярия: 2 товаров
|
|
||||||
|
|
||||||
Товары с остатком менее 10 единиц:
|
|
||||||
- Стул офисный Ergohuman: 8 шт.
|
|
||||||
- Клавиатура Mechanical: 0 шт.
|
|
||||||
- Стол письменный: 5 шт.
|
|
||||||
@ -1,8 +1,3 @@
|
|||||||
"""
|
|
||||||
Модуль управления складскими запасами интернет-магазина
|
|
||||||
Содержит функции для работы с товарами, фильтрации, анализа и отчётности
|
|
||||||
"""
|
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import os
|
import os
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
@ -10,15 +5,6 @@ from collections import Counter
|
|||||||
|
|
||||||
|
|
||||||
def load_products(filepath: str) -> List[Dict]:
|
def load_products(filepath: str) -> List[Dict]:
|
||||||
"""
|
|
||||||
Загружает данные о товарах из CSV-файла.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
filepath: Путь к CSV-файлу
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Список словарей с данными о товарах. При отсутствии файла возвращает пустой список
|
|
||||||
"""
|
|
||||||
products = []
|
products = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -45,15 +31,6 @@ def load_products(filepath: str) -> List[Dict]:
|
|||||||
|
|
||||||
|
|
||||||
def validate_product(product: Dict) -> bool:
|
def validate_product(product: Dict) -> bool:
|
||||||
"""
|
|
||||||
Проверяет корректность данных товара.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
product: Словарь с данными товара
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True, если все поля присутствуют и корректны, иначе False
|
|
||||||
"""
|
|
||||||
required_fields = ['product_id', 'name', 'category', 'quantity', 'price', 'supplier']
|
required_fields = ['product_id', 'name', 'category', 'quantity', 'price', 'supplier']
|
||||||
|
|
||||||
for field in required_fields:
|
for field in required_fields:
|
||||||
@ -85,73 +62,25 @@ def validate_product(product: Dict) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def filter_by_category(products: List[Dict], category: str) -> List[Dict]:
|
def filter_by_category(products: List[Dict], category: str) -> List[Dict]:
|
||||||
"""
|
|
||||||
Фильтрует товары по категории (регистронезависимо).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
category: Название категории для фильтрации
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Новый список товаров указанной категории
|
|
||||||
"""
|
|
||||||
return [product for product in products
|
return [product for product in products
|
||||||
if product['category'].lower() == category.lower()]
|
if product['category'].lower() == category.lower()]
|
||||||
|
|
||||||
|
|
||||||
def filter_by_quantity(products: List[Dict], min_quantity: int) -> List[Dict]:
|
def filter_by_quantity(products: List[Dict], min_quantity: int) -> List[Dict]:
|
||||||
"""
|
|
||||||
Фильтрует товары с остатком не ниже заданного.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
min_quantity: Минимальное количество
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Отфильтрованный список товаров
|
|
||||||
"""
|
|
||||||
return [product for product in products
|
return [product for product in products
|
||||||
if product['quantity'] >= min_quantity]
|
if product['quantity'] >= min_quantity]
|
||||||
|
|
||||||
|
|
||||||
def calculate_total_value(products: List[Dict]) -> float:
|
def calculate_total_value(products: List[Dict]) -> float:
|
||||||
"""
|
|
||||||
Вычисляет общую стоимость всех товаров на складе.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Сумма произведений quantity * price для каждого товара
|
|
||||||
"""
|
|
||||||
return sum(product['quantity'] * product['price'] for product in products)
|
return sum(product['quantity'] * product['price'] for product in products)
|
||||||
|
|
||||||
|
|
||||||
def find_low_stock(products: List[Dict], threshold: int) -> List[Dict]:
|
def find_low_stock(products: List[Dict], threshold: int) -> List[Dict]:
|
||||||
"""
|
|
||||||
Находит товары с критически низким остатком.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
threshold: Пороговое значение
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Список товаров с quantity <= threshold, отсортированный по возрастанию остатка
|
|
||||||
"""
|
|
||||||
low_stock = [product for product in products if product['quantity'] <= threshold]
|
low_stock = [product for product in products if product['quantity'] <= threshold]
|
||||||
return sorted(low_stock, key=lambda x: x['quantity'])
|
return sorted(low_stock, key=lambda x: x['quantity'])
|
||||||
|
|
||||||
|
|
||||||
def group_by_supplier(products: List[Dict]) -> Dict[str, Dict]:
|
def group_by_supplier(products: List[Dict]) -> Dict[str, Dict]:
|
||||||
"""
|
|
||||||
Группирует товары по поставщикам.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Словарь, где ключ — поставщик, значение — словарь со статистикой
|
|
||||||
"""
|
|
||||||
suppliers = {}
|
suppliers = {}
|
||||||
|
|
||||||
for product in products:
|
for product in products:
|
||||||
@ -169,15 +98,6 @@ def group_by_supplier(products: List[Dict]) -> Dict[str, Dict]:
|
|||||||
|
|
||||||
|
|
||||||
def get_most_expensive_product(products: List[Dict]) -> Optional[Dict]:
|
def get_most_expensive_product(products: List[Dict]) -> Optional[Dict]:
|
||||||
"""
|
|
||||||
Находит самый дорогой товар.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Словарь товара с максимальной ценой, при пустом списке возвращает None
|
|
||||||
"""
|
|
||||||
if not products:
|
if not products:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -185,32 +105,12 @@ def get_most_expensive_product(products: List[Dict]) -> Optional[Dict]:
|
|||||||
|
|
||||||
|
|
||||||
def search_by_name(products: List[Dict], keyword: str) -> List[Dict]:
|
def search_by_name(products: List[Dict], keyword: str) -> List[Dict]:
|
||||||
"""
|
|
||||||
Ищет товары по ключевому слову в названии (регистронезависимо).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
keyword: Ключевое слово для поиска
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Список товаров, содержащих ключевое слово в названии
|
|
||||||
"""
|
|
||||||
keyword_lower = keyword.lower()
|
keyword_lower = keyword.lower()
|
||||||
return [product for product in products
|
return [product for product in products
|
||||||
if keyword_lower in product['name'].lower()]
|
if keyword_lower in product['name'].lower()]
|
||||||
|
|
||||||
|
|
||||||
def save_inventory_report(products: List[Dict], filepath: str) -> bool:
|
def save_inventory_report(products: List[Dict], filepath: str) -> bool:
|
||||||
"""
|
|
||||||
Сохраняет инвентаризационный отчёт в текстовый файл.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
products: Список товаров
|
|
||||||
filepath: Путь для сохранения отчёта
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True при успешной записи, False при ошибке
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
||||||
|
|
||||||
@ -245,9 +145,6 @@ def save_inventory_report(products: List[Dict], filepath: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def create_products_csv():
|
def create_products_csv():
|
||||||
"""
|
|
||||||
Создаёт файл data/products.csv с тестовыми данными
|
|
||||||
"""
|
|
||||||
os.makedirs('data', exist_ok=True)
|
os.makedirs('data', exist_ok=True)
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
@ -270,9 +167,6 @@ def create_products_csv():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
|
||||||
Главная функция программы, выполняющая все шаги по анализу складских запасов.
|
|
||||||
"""
|
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
print("УПРАВЛЕНИЕ СКЛАДСКИМИ ЗАПАСАМИ ИНТЕРНЕТ-МАГАЗИНА")
|
print("УПРАВЛЕНИЕ СКЛАДСКИМИ ЗАПАСАМИ ИНТЕРНЕТ-МАГАЗИНА")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
Loading…
Reference in New Issue
Block a user