""" Генератор номеров документов для различных операций в inventory. """ from inventory.models import DocumentCounter def generate_writeoff_document_number(): """ Генерирует уникальный номер документа списания. Формат: WO-XXXXXX (6 цифр) Thread-safe через DocumentCounter. Returns: str: Сгенерированный номер документа (например, WO-000001) """ next_number = DocumentCounter.get_next_value('writeoff') return f"WO-{next_number:06d}" def generate_transfer_document_number(): """ Генерирует уникальный номер документа перемещения. Формат: MOVE-XXXXXX (6 цифр) Returns: str: Сгенерированный номер документа (например, MOVE-000001) """ next_number = DocumentCounter.get_next_value('transfer') return f"MOVE-{next_number:06d}" def generate_incoming_document_number(): """ Генерирует номер документа поступления вида 'IN-XXXX-XXXX'. Алгоритм: 1. Ищет максимальный номер в БД с префиксом 'IN-' 2. Извлекает числовое значение из последней части (IN-XXXX-XXXX) 3. Увеличивает на 1 и форматирует в 'IN-XXXX-XXXX' Преимущества: - Работает без SEQUENCE (не требует миграций) - Гарантирует уникальность через unique constraint в модели - Простая логика, легко отладить - Работает с любым тенантом (django-tenants совместимо) Возвращает: str: Номер вида 'IN-0000-0001', 'IN-0000-0002', итд """ from inventory.models import IncomingBatch import logging import os # Настройка логирования LOG_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs', 'incoming_sequence.log') os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True) file_logger = logging.getLogger('incoming_sequence_file') if not file_logger.handlers: handler = logging.FileHandler(LOG_FILE, encoding='utf-8') formatter = logging.Formatter( '%(asctime)s | %(levelname)s | %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) handler.setFormatter(formatter) file_logger.addHandler(handler) file_logger.setLevel(logging.DEBUG) logger = logging.getLogger('inventory.incoming') try: # Найти все номера с префиксом IN- existing_batches = IncomingBatch.objects.filter( document_number__startswith='IN-' ).values_list('document_number', flat=True).order_by('document_number') if not existing_batches: # Если нет номеров - начинаем с 1 next_num = 1 file_logger.info(f"✓ No existing batches found, starting from 1") else: # Берем последний номер, извлекаем цифру и увеличиваем last_number = existing_batches.last() # 'IN-0000-0005' # Извлекаем последние 4 цифры last_digits = int(last_number.split('-')[-1]) # 5 next_num = last_digits + 1 file_logger.info(f"✓ Last number was {last_number}, next: {next_num}") # Форматируем в IN-XXXX-XXXX combined_str = f"{next_num:08d}" # Гарантируем 8 цифр first_part = combined_str[:4] # '0000' или '0001' second_part = combined_str[4:] # '0001' или '0002' result = f"IN-{first_part}-{second_part}" file_logger.info(f"✓ Generated: {result}") return result except Exception as e: file_logger.error(f"✗ Error generating number: {str(e)}") raise