Исправлена форма заказа: две колонки и корректная работа кнопки сохранения

- Разделен экран на две колонки: заказ слева, оплата справа
- Форма оплаты вынесена за пределы основной формы заказа (устранена проблема вложенных форм)
- Исправлен метод calculate_total() для сохранения итоговой суммы в БД
- Добавлена модель Transaction для учета платежей и возвратов
- Добавлена модель PaymentMethod для методов оплаты
- Удалена старая модель Payment, заменена на Transaction
- Добавлен TransactionService для управления транзакциями
- Обновлен интерфейс форм оплаты для правой колонки
- Кнопка 'Сохранить изменения' теперь работает корректно
This commit is contained in:
2025-11-29 14:33:23 +03:00
parent 438ca5d515
commit c1351e1f49
14 changed files with 1188 additions and 548 deletions

View File

@@ -317,15 +317,38 @@ class Order(models.Model):
self.delivery_cost = DeliveryCostCalculator.calculate(self)
def calculate_total(self):
"""Рассчитывает итоговую сумму заказа"""
"""Рассчитывает итоговую сумму заказа и сохраняет её в БД"""
items_total = sum(item.get_total_price() for item in self.items.all())
# Пересчитываем стоимость доставки если она автоматическая
self.recalculate_delivery_cost()
self.total_amount = items_total + self.delivery_cost
# Сохраняем изменения в БД
self.save(update_fields=['total_amount', 'delivery_cost', 'is_custom_delivery_cost'])
return self.total_amount
def recalculate_amount_paid(self):
"""
Пересчитывает оплаченную сумму на основе транзакций.
amount_paid = сумма_платежей - суммаозвратов
"""
from django.db.models import Sum, Q
from decimal import Decimal
payments_sum = self.transactions.filter(
transaction_type='payment'
).aggregate(total=Sum('amount'))['total'] or Decimal('0')
refunds_sum = self.transactions.filter(
transaction_type='refund'
).aggregate(total=Sum('amount'))['total'] or Decimal('0')
self.amount_paid = payments_sum - refunds_sum
self.update_payment_status()
def update_payment_status(self):
"""Автоматически обновляет статус оплаты на основе amount_paid"""
if self.amount_paid >= self.total_amount:
@@ -337,7 +360,8 @@ class Order(models.Model):
else:
self.payment_status = 'unpaid'
self.is_paid = False
self.save()
# Сохраняем только изменённые поля для оптимизации
self.save(update_fields=['payment_status', 'is_paid', 'amount_paid'])
def is_draft(self):
"""Проверяет, является ли заказ черновиком"""
@@ -348,6 +372,11 @@ class Order(models.Model):
"""Остаток к оплате"""
return max(self.total_amount - self.amount_paid, 0)
@property
def subtotal(self):
"""Сумма только товаров (без доставки)"""
return sum(item.get_total_price() for item in self.items.all())
@property
def delivery_cost_display(self):
"""