Добавлен статус 'converted_to_writeoff' для резервов документов списания

Проблема:
- Резервы документов списания помечались как 'converted_to_sale'
- Это вводило в заблуждение - списание это не продажа
- В админке резервы списания отображались как 'В продажу'

Решение:
- Добавлен новый статус 'converted_to_writeoff' в Reservation.STATUS_CHOICES
- Увеличен max_length поля status с 20 до 25 символов
- Обновлен WriteOffDocumentService.confirm_document() - теперь использует новый статус
- Обновлено описание поля converted_at (теперь для продажи ИЛИ списания)
- Создана миграция 0011_add_writeoff_status_to_reservation

Изменения:
- inventory/models.py: добавлен статус, увеличен max_length, обновлен help_text
- inventory/services/writeoff_document_service.py: используется converted_to_writeoff
- inventory/migrations/0011_*.py: миграция для изменений модели

Влияние:
- Чистая аналитика: можно отличить продажи от списаний
- Корректный учёт Stock: статус влияет на quantity_reserved
- Защита от ошибок при будущих доработках (откат списания)
This commit is contained in:
2025-12-11 21:52:09 +03:00
parent cf5dee8657
commit 8d7869e9e7
3 changed files with 29 additions and 4 deletions

View File

@@ -404,6 +404,7 @@ class Reservation(models.Model):
('reserved', 'Зарезервирован'),
('released', 'Освобожден'),
('converted_to_sale', 'Преобразован в продажу'),
('converted_to_writeoff', 'Преобразован в списание'),
]
order_item = models.ForeignKey('orders.OrderItem', on_delete=models.CASCADE,
@@ -422,12 +423,13 @@ class Reservation(models.Model):
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE,
related_name='reservations', verbose_name="Склад")
quantity = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Количество")
status = models.CharField(max_length=20, choices=STATUS_CHOICES,
status = models.CharField(max_length=25, choices=STATUS_CHOICES,
default='reserved', verbose_name="Статус")
reserved_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата резервирования")
released_at = models.DateTimeField(null=True, blank=True, verbose_name="Дата освобождения")
converted_at = models.DateTimeField(null=True, blank=True,
verbose_name="Дата преобразования в продажу")
verbose_name="Дата преобразования",
help_text="Дата преобразования в продажу или списание")
# Soft Lock для корзины POS (витринные комплекты)
cart_lock_expires_at = models.DateTimeField(