# -*- coding: utf-8 -*- """ Сервис для управления единицами измерения. Отвечает за создание и управление справочником единиц измерения (UnitOfMeasure). """ import logging from typing import List, Dict, Any logger = logging.getLogger(__name__) class UnitOfMeasureService: """ Сервис для управления единицами измерения. Предоставляет методы для создания и управления базовыми единицами измерения, которые используются в системе для товаров и продаж. """ # Базовый набор единиц измерения для новых тенантов DEFAULT_UNITS = [ # Базовые единицы (из старых UNIT_CHOICES) {'code': 'шт', 'name': 'Штука', 'short_name': 'шт.', 'position': 1}, {'code': 'м', 'name': 'Метр', 'short_name': 'м.', 'position': 2}, {'code': 'г', 'name': 'Грамм', 'short_name': 'г.', 'position': 3}, {'code': 'л', 'name': 'Литр', 'short_name': 'л.', 'position': 4}, {'code': 'кг', 'name': 'Килограмм', 'short_name': 'кг.', 'position': 5}, # Флористические единицы {'code': 'банч', 'name': 'Банч', 'short_name': 'банч', 'position': 10}, {'code': 'ветка', 'name': 'Ветка', 'short_name': 'вет.', 'position': 11}, {'code': 'пучок', 'name': 'Пучок', 'short_name': 'пуч.', 'position': 12}, {'code': 'коробка', 'name': 'Коробка', 'short_name': 'кор.', 'position': 13}, ] @classmethod def create_default_units(cls) -> List: """ Создает базовый набор единиц измерения для тенанта. Использует get_or_create, поэтому безопасно вызывать повторно. Returns: List[UnitOfMeasure]: Список созданных/существующих единиц измерения """ from products.models import UnitOfMeasure created_units = [] for unit_data in cls.DEFAULT_UNITS: unit, created = UnitOfMeasure.objects.get_or_create( code=unit_data['code'], defaults={ 'name': unit_data['name'], 'short_name': unit_data['short_name'], 'position': unit_data['position'], 'is_active': True, } ) created_units.append(unit) if created: logger.debug(f"Создана единица измерения: {unit.code} - {unit.name}") logger.info(f"Инициализация единиц измерения завершена: {len(created_units)} единиц") return created_units @classmethod def reset_default_units(cls) -> List: """ Удаляет все единицы измерения и создаёт их заново. ВНИМАНИЕ: Используйте только при инициализации тенанта или в тестах! Удаление единиц может нарушить связи с существующими товарами. Returns: List[UnitOfMeasure]: Список созданных единиц измерения """ from products.models import UnitOfMeasure logger.warning("Удаление всех единиц измерения...") UnitOfMeasure.objects.all().delete() return cls.create_default_units() @classmethod def get_or_create_unit(cls, code: str, name: str, short_name: str, position: int = 0) -> tuple: """ Получает или создаёт единицу измерения. Args: code: Уникальный код единицы name: Полное название short_name: Короткое название для UI position: Позиция для сортировки Returns: tuple: (UnitOfMeasure, created) - единица и флаг создания """ from products.models import UnitOfMeasure unit, created = UnitOfMeasure.objects.get_or_create( code=code, defaults={ 'name': name, 'short_name': short_name, 'position': position, 'is_active': True, } ) if created: logger.info(f"Создана единица измерения: {code} - {name}") return unit, created @classmethod def get_unit_by_code(cls, code: str): """ Получает единицу измерения по коду. Args: code: Код единицы измерения Returns: UnitOfMeasure или None, если не найдена """ from products.models import UnitOfMeasure try: return UnitOfMeasure.objects.get(code=code, is_active=True) except UnitOfMeasure.DoesNotExist: logger.warning(f"Единица измерения с кодом '{code}' не найдена") return None @classmethod def get_active_units(cls) -> List: """ Возвращает все активные единицы измерения. Returns: List[UnitOfMeasure]: Список активных единиц, отсортированных по position """ from products.models import UnitOfMeasure return list(UnitOfMeasure.objects.filter(is_active=True).order_by('position', 'code'))