# -*- coding: utf-8 -*- """ Утилиты для модуля inventory (склад, приходы, продажи, партии). """ import re import os import logging from datetime import datetime # Настройка логирования в файл LOG_FILE = os.path.join(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) 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 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