Files
octopus/myproject/orders/services/order_status_service.py
Andrey Smakotin 9a44c98e6e Simplify order creation and editing - remove autosave
- Removed autosave.js (665 lines) and draft-creator.js (441 lines)
- Removed draft_service.py (~500 lines) and DraftOrderService
- Removed AJAX endpoints: autosave and create-draft
- Updated order_create() to add is_create_page flag
- Updated order_update() to finalize drafts without DraftOrderService
- Added get_new_status() method to OrderStatusService
- Updated order_form.html:
  - Removed old JS includes
  - Added beforeunload warning for unsaved data
  - Updated buttons: separate buttons for create/draft/finalize
- Total code reduction: ~1600 lines (92% removed)

New workflow:
- /orders/create/ - user fills form, chooses button
- /orders/<id>/edit/ - simple editing without autosave
- beforeunload warning when leaving page (except on submit)
2025-11-28 23:29:19 +03:00

236 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Сервис для управления статусами заказов.
Содержит бизнес-логику для работы со статусами и их переходами.
"""
from django.db import transaction
from orders.models import OrderStatus, Order
class OrderStatusService:
"""Сервис для работы со статусами заказов"""
@staticmethod
def get_default_status():
"""
Возвращает статус по умолчанию для новых заказов ('new')
"""
try:
return OrderStatus.objects.get(code='new', is_system=True)
except OrderStatus.DoesNotExist:
return None
@staticmethod
def get_draft_status():
"""Возвращает системный статус 'draft' (черновик)"""
try:
return OrderStatus.objects.get(code='draft', is_system=True)
except OrderStatus.DoesNotExist:
return None
@staticmethod
def get_new_status():
"""Возвращает системный статус 'new' (новый заказ)"""
status, created = OrderStatus.objects.get_or_create(
code='new',
defaults={
'name': 'Новый',
'label': 'Новый',
'is_system': True,
'color': '#0d6efd',
'order': 10,
}
)
return status
@staticmethod
def get_system_status(code):
"""Получить системный статус по коду"""
try:
return OrderStatus.objects.get(code=code, is_system=True)
except OrderStatus.DoesNotExist:
return None
@staticmethod
def create_default_statuses():
"""
Создает системные статусы для тенанта.
Вызывается при первом использовании или миграции.
"""
default_statuses = [
{
'code': 'draft',
'name': 'Черновик',
'label': 'Черновик',
'is_system': True,
'order': 0,
'color': '#9E9E9E',
'description': 'Заказ находится в процессе создания/редактирования'
},
{
'code': 'new',
'name': 'Новый',
'label': 'Новый',
'is_system': True,
'order': 10,
'color': '#2196F3',
'description': 'Новый заказ, ожидающий обработки'
},
{
'code': 'confirmed',
'name': 'Подтвержден',
'label': 'Подтвержден',
'is_system': True,
'order': 20,
'color': '#FF9800',
'description': 'Заказ подтвержден и одобрен'
},
{
'code': 'in_assembly',
'name': 'В сборке',
'label': 'В сборке',
'is_system': True,
'order': 30,
'color': '#FF9800',
'description': 'Заказ находится в процессе сборки/подготовки'
},
{
'code': 'in_delivery',
'name': 'В доставке',
'label': 'В доставке',
'is_system': True,
'order': 40,
'color': '#9C27B0',
'description': 'Заказ в пути к клиенту'
},
{
'code': 'completed',
'name': 'Выполнен',
'label': 'Выполнен',
'is_system': True,
'is_positive_end': True,
'order': 50,
'color': '#4CAF50',
'description': 'Заказ успешно доставлен/выполнен'
},
{
'code': 'return',
'name': 'Возврат',
'label': 'Возврат',
'is_system': True,
'order': 60,
'color': '#FF5722',
'description': 'Заказ возвращен клиентом'
},
{
'code': 'cancelled',
'name': 'Отменен',
'label': 'Отменен',
'is_system': True,
'is_negative_end': True,
'order': 70,
'color': '#F44336',
'description': 'Заказ отменен'
},
]
for status_data in default_statuses:
OrderStatus.objects.get_or_create(
code=status_data['code'],
defaults=status_data
)
@staticmethod
@transaction.atomic
def change_order_status(order, new_status, user, notes=""):
"""
Меняет статус заказа и выполняет соответствующую бизнес-логику.
Args:
order (Order): Экземпляр заказа
new_status (OrderStatus): Новый статус
user (CustomUser): Пользователь, делающий изменение
notes (str): Опциональные заметки
Returns:
Order: Обновленный экземпляр заказа
Raises:
ValueError: Если статус не может быть применен
"""
old_status = order.status
order.status = new_status
order.modified_by = user
order.save()
# Запустить бизнес-логику в зависимости от нового статуса
if new_status.code == 'completed':
_handle_order_completion(order, user)
elif new_status.code == 'cancelled':
_handle_order_cancellation(order, old_status, user)
elif new_status.code == 'return':
_handle_order_return(order, user)
return order
@staticmethod
def get_all_statuses():
"""Возвращает все статусы, отсортированные по порядку"""
return OrderStatus.objects.all().order_by('order', 'name')
@staticmethod
def get_system_statuses():
"""Возвращает только системные статусы"""
return OrderStatus.objects.filter(is_system=True).order_by('order')
@staticmethod
def get_custom_statuses():
"""Возвращает только пользовательские статусы"""
return OrderStatus.objects.filter(is_system=False).order_by('order', 'name')
def _handle_order_completion(order, user):
"""
Обработка при переводе в статус 'Выполнен'.
Здесь происходит списание товаров со склада.
TODO: Интеграция с inventory приложением
"""
# from inventory.services import InventoryService
# InventoryService.process_order_completion(order)
pass
def _handle_order_cancellation(order, old_status, user):
"""
Обработка при переводе в статус 'Отменен'.
Если заказ был выполнен - возвращаем товары и деньги.
"""
if old_status and old_status.code == 'completed':
# Заказ был выполнен - нужно вернуть товары и деньги
order.is_returned = True
order.save()
# TODO: Интеграция с inventory - возврат товаров
# InventoryService.process_order_return(order)
# TODO: Интеграция с платежами - создать возврат
# PaymentService.create_refund(order)
else:
# Заказ отменен до выполнения - просто отменить резервы
# TODO: InventoryService.cancel_order_reservation(order)
pass
def _handle_order_return(order, user):
"""
Обработка при переводе в статус 'Возврат'.
Это промежуточный статус перед окончательной отменой.
"""
order.is_returned = True
order.save()
# TODO: Интеграция с inventory - вернуть товары на склад
# InventoryService.process_order_return(order)