diff --git a/myproject/customers/templates/customers/customer_detail.html b/myproject/customers/templates/customers/customer_detail.html index 7b3ecb5..aa7ad78 100644 --- a/myproject/customers/templates/customers/customer_detail.html +++ b/myproject/customers/templates/customers/customer_detail.html @@ -126,7 +126,7 @@ {{ transaction.description|default:"-" }} {% if transaction.order %} - + #{{ transaction.order.order_number }} {% else %} @@ -237,10 +237,10 @@ {% endif %} - + - + diff --git a/myproject/inventory/templates/inventory/reservation/reservation_list.html b/myproject/inventory/templates/inventory/reservation/reservation_list.html index d7c22e0..460c228 100644 --- a/myproject/inventory/templates/inventory/reservation/reservation_list.html +++ b/myproject/inventory/templates/inventory/reservation/reservation_list.html @@ -69,8 +69,8 @@ {% if r.order_item %} - - Заказ #{{ r.order_item.order.id }} + + Заказ #{{ r.order_item.order.order_number }} {% else %} diff --git a/myproject/orders/forms.py b/myproject/orders/forms.py index ed3c454..6fb01e1 100644 --- a/myproject/orders/forms.py +++ b/myproject/orders/forms.py @@ -263,13 +263,15 @@ class OrderItemForm(forms.ModelForm): self.fields['is_custom_price'].required = False def clean_price(self): - """Парсим цену с запятой или точкой""" + """Парсим цену с запятой или точкой и округляем до 2 знаков""" value = self.cleaned_data.get('price') if value in (None, ''): return None value_str = str(value).strip().replace(',', '.') try: - return Decimal(value_str) + price = Decimal(value_str) + # Округляем до 2 знаков после запятой + return price.quantize(Decimal('0.01')) except Exception: raise forms.ValidationError('Введите число.') diff --git a/myproject/orders/models/order.py b/myproject/orders/models/order.py index e9c887b..4d92eaa 100644 --- a/myproject/orders/models/order.py +++ b/myproject/orders/models/order.py @@ -248,6 +248,11 @@ class Order(models.Model): def __str__(self): return f"Заказ #{self.order_number} - {self.customer}" + def get_absolute_url(self): + """Возвращает канонический URL для заказа""" + from django.urls import reverse + return reverse('orders:order-detail', kwargs={'order_number': self.order_number}) + def save(self, *args, **kwargs): # Генерируем уникальный номер заказа при создании (начиная с 100 для 3-значного поиска) if not self.order_number: diff --git a/myproject/orders/models/payment.py b/myproject/orders/models/payment.py index 18fa37e..5df762c 100644 --- a/myproject/orders/models/payment.py +++ b/myproject/orders/models/payment.py @@ -172,9 +172,11 @@ class Payment(models.Model): ) # Нормализация переплаты: лишнее в кошелёк, amount_paid = total_amount - try: - from customers.services.wallet_service import WalletService - WalletService.add_overpayment(self.order, self.created_by) - except Exception: - # Продолжаем, даже если нормализация переплаты не удалась - pass + # ТОЛЬКО для новых платежей, чтобы избежать дублирования при обновлении + if is_new: + try: + from customers.services.wallet_service import WalletService + WalletService.add_overpayment(self.order, self.created_by) + except Exception: + # Продолжаем, даже если нормализация переплаты не удалась + pass diff --git a/myproject/orders/static/orders/js/autosave.js b/myproject/orders/static/orders/js/autosave.js index ed1d554..44baf61 100644 --- a/myproject/orders/static/orders/js/autosave.js +++ b/myproject/orders/static/orders/js/autosave.js @@ -11,14 +11,14 @@ // Конфигурация const CONFIG = { AUTOSAVE_DELAY: 3000, // Задержка перед автосохранением (мс) - AUTOSAVE_URL_PATTERN: '/orders/{orderId}/autosave/', + AUTOSAVE_URL_PATTERN: '/orders/{orderNumber}/autosave/', STATUS_DISPLAY_DURATION: 5000, // Длительность показа статуса (мс) }; // Состояние модуля let autosaveTimer = null; let isAutosaving = false; - let orderId = null; + let orderNumber = null; /** * Инициализация модуля автосохранения @@ -35,12 +35,12 @@ return; } - // Получаем ID заказа из URL + // Получаем номер заказа из URL const urlMatch = window.location.pathname.match(/\/orders\/(\d+)\/edit\//); if (!urlMatch) { return; } - orderId = urlMatch[1]; + orderNumber = urlMatch[1]; // Инициализируем UI индикатора initStatusIndicator(); @@ -314,7 +314,7 @@ const formData = collectFormData(); // Отправляем AJAX запрос - const url = CONFIG.AUTOSAVE_URL_PATTERN.replace('{orderId}', orderId); + const url = CONFIG.AUTOSAVE_URL_PATTERN.replace('{orderNumber}', orderNumber); const response = await fetch(url, { method: 'POST', headers: { diff --git a/myproject/orders/templates/orders/order_confirm_delete.html b/myproject/orders/templates/orders/order_confirm_delete.html index ecb2fc9..5e9d812 100644 --- a/myproject/orders/templates/orders/order_confirm_delete.html +++ b/myproject/orders/templates/orders/order_confirm_delete.html @@ -50,7 +50,7 @@
{% csrf_token %}
- + Отмена
- + Редактировать - + Удалить @@ -250,7 +250,7 @@

Можно использовать для оплаты этого заказа

- + {% csrf_token %}