from django.db import models from accounts.models import CustomUser class PaymentMethod(models.Model): """ Способ оплаты заказа. Справочник для управления доступными методами оплаты. """ # Код для программного доступа code = models.SlugField( unique=True, max_length=50, verbose_name="Код способа оплаты", help_text="Уникальный идентификатор (например: 'cash_to_courier', 'card_to_courier')" ) # Отображаемое название name = models.CharField( max_length=100, verbose_name="Название способа оплаты" ) # Описание description = models.TextField( blank=True, verbose_name="Описание", help_text="Дополнительная информация о способе оплаты" ) # Активность is_active = models.BooleanField( default=True, verbose_name="Активен", help_text="Отключенные способы оплаты не отображаются при создании заказа" ) # Порядок отображения order = models.PositiveIntegerField( default=0, verbose_name="Порядок отображения" ) # Системный флаг is_system = models.BooleanField( default=False, verbose_name="Системный", help_text="Системные способы оплаты нельзя удалить через интерфейс" ) # Аудит created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) created_by = models.ForeignKey( CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='created_payment_methods', verbose_name="Создано" ) class Meta: verbose_name = "Способ оплаты" verbose_name_plural = "Способы оплаты" ordering = ['order', 'name'] indexes = [ models.Index(fields=['code']), models.Index(fields=['is_active']), models.Index(fields=['order']), ] def __str__(self): return self.name class Payment(models.Model): """ Платеж по заказу. Хранит историю всех платежей, включая частичные оплаты. Поддерживает смешанную оплату (несколько платежей разными способами на один заказ). """ order = models.ForeignKey( 'Order', on_delete=models.CASCADE, related_name='payments', verbose_name="Заказ" ) amount = models.DecimalField( max_digits=10, decimal_places=2, verbose_name="Сумма платежа" ) payment_method = models.ForeignKey( 'PaymentMethod', on_delete=models.PROTECT, related_name='payments', verbose_name="Способ оплаты", help_text="Способ оплаты данного платежа" ) payment_date = models.DateTimeField( auto_now_add=True, verbose_name="Дата и время платежа" ) created_by = models.ForeignKey( CustomUser, on_delete=models.SET_NULL, null=True, blank=True, related_name='payments_created', verbose_name="Принял платеж" ) notes = models.TextField( blank=True, null=True, verbose_name="Примечания", help_text="Дополнительная информация о платеже" ) class Meta: verbose_name = "Платеж" verbose_name_plural = "Платежи" ordering = ['-payment_date'] indexes = [ models.Index(fields=['order']), models.Index(fields=['payment_date']), ] def __str__(self): return f"Платеж {self.amount} руб. по заказу #{self.order.order_number}" def save(self, *args, **kwargs): """При сохранении платежа обновляем сумму оплаты в заказе""" super().save(*args, **kwargs) # Пересчитываем общую сумму оплаты в заказе self.order.amount_paid = sum(p.amount for p in self.order.payments.all()) self.order.update_payment_status() # Нормализация переплаты: лишнее в кошелёк, amount_paid = total_amount try: from customers.services.wallet_service import WalletService WalletService.add_overpayment(self.order, self.created_by) except Exception: # Если обработка переплаты не удалась, продолжаем без ошибок pass