feat(pos): добавлен полноценный интерфейс скидок в модальное окно продажи
- Добавлен API endpoint /pos/api/discounts/available/ для получения списка доступных скидок - Добавлен метод DiscountApplier.apply_manual_discount() для применения ручных скидок - Обновлен POS checkout для обработки manual_discount_id - Расширена секция скидок в модальном окне: * Отображение автоматических скидок (read-only) * Dropdown для выбора скидки вручную * Подробная детализация: подитог, общая скидка, скидки на позиции * Поле промокода с иконкой - Увеличен размер модального окна и изменено соотношение колонок (5/7) - Убрана вертикальная прокрутка из модального окна Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -214,6 +214,69 @@ class DiscountApplier:
|
||||
# Пересчитываем
|
||||
order.calculate_total()
|
||||
|
||||
@staticmethod
|
||||
@transaction.atomic
|
||||
def apply_manual_discount(order, discount, user=None):
|
||||
"""
|
||||
Применить скидку вручную к заказу.
|
||||
|
||||
Args:
|
||||
order: Order
|
||||
discount: Discount
|
||||
user: CustomUser (применивший скидку)
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'success': bool,
|
||||
'discount_amount': Decimal,
|
||||
'error': str
|
||||
}
|
||||
"""
|
||||
from discounts.models import DiscountApplication
|
||||
|
||||
# Проверяем scope скидки
|
||||
if discount.scope != 'order':
|
||||
return {'success': False, 'error': 'Эта скидка не применяется к заказу'}
|
||||
|
||||
# Проверяем мин. сумму
|
||||
if discount.min_order_amount and order.subtotal < discount.min_order_amount:
|
||||
return {'success': False, 'error': f'Мин. сумма заказа: {discount.min_order_amount} руб.'}
|
||||
|
||||
# Удаляем предыдущую скидку на заказ
|
||||
DiscountApplier._remove_order_discount_only(order)
|
||||
|
||||
# Рассчитываем сумму
|
||||
discount_amount = discount.calculate_discount_amount(Decimal(order.subtotal))
|
||||
|
||||
# Применяем к заказу
|
||||
order.applied_discount = discount
|
||||
order.discount_amount = discount_amount
|
||||
order.save(update_fields=['applied_discount', 'discount_amount'])
|
||||
|
||||
# Пересчитываем total_amount
|
||||
order.calculate_total()
|
||||
|
||||
# Создаем запись о применении
|
||||
DiscountApplication.objects.create(
|
||||
order=order,
|
||||
discount=discount,
|
||||
target='order',
|
||||
base_amount=order.subtotal,
|
||||
discount_amount=discount_amount,
|
||||
final_amount=order.subtotal - discount_amount,
|
||||
customer=order.customer,
|
||||
applied_by=user
|
||||
)
|
||||
|
||||
# Увеличиваем счетчик использований скидки
|
||||
discount.current_usage_count += 1
|
||||
discount.save(update_fields=['current_usage_count'])
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'discount_amount': discount_amount
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _remove_order_discount_only(order):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user