fix(forms): использовать format_decimal для input type=number
Заменён floatformat на format_decimal в полях input type="number", чтобы числа всегда использовали точку как десятичный разделитель, независимо от локали. Это исправляет ошибки парсинга в браузере. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
{% extends "system_settings/base_settings.html" %}
|
{% extends "system_settings/base_settings.html" %}
|
||||||
|
{% load inventory_filters %}
|
||||||
|
|
||||||
{% block title %}{% if is_edit %}Редактирование скидки{% else %}Создание скидки{% endif %}{% endblock %}
|
{% block title %}{% if is_edit %}Редактирование скидки{% else %}Создание скидки{% endif %}{% endblock %}
|
||||||
|
|
||||||
@@ -33,13 +34,13 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_name" class="form-label">Название * <span class="text-muted small">(макс. 200 символов)</span></label>
|
<label for="id_name" class="form-label">Название * <span class="text-muted small">(макс. 200 символов)</span></label>
|
||||||
<input type="text" class="form-control" id="id_name" name="name"
|
<input type="text" class="form-control" id="id_name" name="name"
|
||||||
value="{% if form.instance.pk %}{{ form.instance.name|default_if_none:'' }}{% else %}{{ form.name.value|default_if_none:'' }}{% endif %}"
|
value="{{ form.name.value|default_if_none:'' }}"
|
||||||
maxlength="200" required>
|
maxlength="200" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_priority" class="form-label">Приоритет</label>
|
<label for="id_priority" class="form-label">Приоритет</label>
|
||||||
<input type="number" class="form-control" id="id_priority" name="priority"
|
<input type="number" class="form-control" id="id_priority" name="priority"
|
||||||
value="{% if form.instance.pk %}{{ form.instance.priority|default_if_none:0 }}{% else %}{{ form.priority.value|default_if_none:0 }}{% endif %}"
|
value="{{ form.priority.value|default_if_none:0 }}"
|
||||||
min="0">
|
min="0">
|
||||||
<div class="form-text">Выше = применяется раньше</div>
|
<div class="form-text">Выше = применяется раньше</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +48,7 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="id_description" class="form-label">Описание</label>
|
<label for="id_description" class="form-label">Описание</label>
|
||||||
<textarea class="form-control" id="id_description" name="description" rows="2">{% if form.instance.pk %}{{ form.instance.description|default_if_none:'' }}{% else %}{{ form.description.value|default_if_none:'' }}{% endif %}</textarea>
|
<textarea class="form-control" id="id_description" name="description" rows="2">{{ form.description.value|default_if_none:'' }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Параметры скидки -->
|
<!-- Параметры скидки -->
|
||||||
@@ -58,15 +59,15 @@
|
|||||||
<select class="form-select" id="id_discount_type" name="discount_type" required>
|
<select class="form-select" id="id_discount_type" name="discount_type" required>
|
||||||
<option value="">Выберите...</option>
|
<option value="">Выберите...</option>
|
||||||
<option value="percentage"
|
<option value="percentage"
|
||||||
{% if form.instance.pk and form.instance.discount_type == 'percentage' or form.discount_type.value == 'percentage' %}selected{% endif %}>Процент</option>
|
{% if form.discount_type.value == 'percentage' %}selected{% endif %}>Процент</option>
|
||||||
<option value="fixed_amount"
|
<option value="fixed_amount"
|
||||||
{% if form.instance.pk and form.instance.discount_type == 'fixed_amount' or form.discount_type.value == 'fixed_amount' %}selected{% endif %}>Фиксированная сумма (руб.)</option>
|
{% if form.discount_type.value == 'fixed_amount' %}selected{% endif %}>Фиксированная сумма (руб.)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="id_value" class="form-label">Значение *</label>
|
<label for="id_value" class="form-label">Значение *</label>
|
||||||
<input type="number" class="form-control" id="id_value" name="value"
|
<input type="number" class="form-control" id="id_value" name="value"
|
||||||
value="{% if form.instance.pk %}{{ form.instance.value|default_if_none:'' }}{% else %}{{ form.value.value|default_if_none:'' }}{% endif %}"
|
value="{{ form.value.value|format_decimal:2|default_if_none:'' }}"
|
||||||
step="0.01" min="0" required>
|
step="0.01" min="0" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
@@ -74,11 +75,11 @@
|
|||||||
<select class="form-select" id="id_scope" name="scope" required>
|
<select class="form-select" id="id_scope" name="scope" required>
|
||||||
<option value="">Выберите...</option>
|
<option value="">Выберите...</option>
|
||||||
<option value="order"
|
<option value="order"
|
||||||
{% if form.instance.pk and form.instance.scope == 'order' or form.scope.value == 'order' %}selected{% endif %}>На весь заказ</option>
|
{% if form.scope.value == 'order' %}selected{% endif %}>На весь заказ</option>
|
||||||
<option value="product"
|
<option value="product"
|
||||||
{% if form.instance.pk and form.instance.scope == 'product' or form.scope.value == 'product' %}selected{% endif %}>На конкретные товары</option>
|
{% if form.scope.value == 'product' %}selected{% endif %}>На конкретные товары</option>
|
||||||
<option value="category"
|
<option value="category"
|
||||||
{% if form.instance.pk and form.instance.scope == 'category' or form.scope.value == 'category' %}selected{% endif %}>На категории товаров</option>
|
{% if form.scope.value == 'category' %}selected{% endif %}>На категории товаров</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -87,7 +88,7 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check form-switch mt-4">
|
<div class="form-check form-switch mt-4">
|
||||||
<input class="form-check-input" type="checkbox" id="id_is_auto" name="is_auto"
|
<input class="form-check-input" type="checkbox" id="id_is_auto" name="is_auto"
|
||||||
{% if form.instance.pk and form.instance.is_auto or form.is_auto.value %}checked{% endif %}>
|
{% if form.is_auto.value %}checked{% endif %}>
|
||||||
<label class="form-check-label" for="id_is_auto">
|
<label class="form-check-label" for="id_is_auto">
|
||||||
Автоматическое применение
|
Автоматическое применение
|
||||||
</label>
|
</label>
|
||||||
@@ -97,7 +98,7 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-check form-switch mt-4">
|
<div class="form-check form-switch mt-4">
|
||||||
<input class="form-check-input" type="checkbox" id="id_is_active" name="is_active"
|
<input class="form-check-input" type="checkbox" id="id_is_active" name="is_active"
|
||||||
{% if form.instance.pk and form.instance.is_active != False or form.is_active.value != False %}checked{% endif %}>
|
{% if form.is_active.value %}checked{% endif %}>
|
||||||
<label class="form-check-label" for="id_is_active">
|
<label class="form-check-label" for="id_is_active">
|
||||||
Активна
|
Активна
|
||||||
</label>
|
</label>
|
||||||
@@ -110,15 +111,15 @@
|
|||||||
<label for="id_combine_mode" class="form-label">Режим объединения с другими скидками</label>
|
<label for="id_combine_mode" class="form-label">Режим объединения с другими скидками</label>
|
||||||
<select class="form-select" id="id_combine_mode" name="combine_mode">
|
<select class="form-select" id="id_combine_mode" name="combine_mode">
|
||||||
<option value="max_only"
|
<option value="max_only"
|
||||||
{% if form.instance.pk and form.instance.combine_mode == 'max_only' or not form.instance.pk and form.combine_mode.value == 'max_only' or not form.combine_mode.value %}selected{% endif %}>
|
{% if form.combine_mode.value == 'max_only' or not form.combine_mode.value %}selected{% endif %}>
|
||||||
🏆 Только максимум (применяется лучшая скидка)
|
🏆 Только максимум (применяется лучшая скидка)
|
||||||
</option>
|
</option>
|
||||||
<option value="stack"
|
<option value="stack"
|
||||||
{% if form.instance.pk and form.instance.combine_mode == 'stack' or not form.instance.pk and form.combine_mode.value == 'stack' %}selected{% endif %}>
|
{% if form.combine_mode.value == 'stack' %}selected{% endif %}>
|
||||||
📚 Складывать (суммировать с другими)
|
📚 Складывать (суммировать с другими)
|
||||||
</option>
|
</option>
|
||||||
<option value="exclusive"
|
<option value="exclusive"
|
||||||
{% if form.instance.pk and form.instance.combine_mode == 'exclusive' or not form.instance.pk and form.combine_mode.value == 'exclusive' %}selected{% endif %}>
|
{% if form.combine_mode.value == 'exclusive' %}selected{% endif %}>
|
||||||
🚫 Исключающая (отменяет остальные скидки)
|
🚫 Исключающая (отменяет остальные скидки)
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -131,14 +132,14 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_min_order_amount" class="form-label">Мин. сумма заказа</label>
|
<label for="id_min_order_amount" class="form-label">Мин. сумма заказа</label>
|
||||||
<input type="number" class="form-control" id="id_min_order_amount" name="min_order_amount"
|
<input type="number" class="form-control" id="id_min_order_amount" name="min_order_amount"
|
||||||
value="{% if form.instance.pk %}{{ form.instance.min_order_amount|default_if_none:'' }}{% else %}{{ form.min_order_amount.value|default_if_none:'' }}{% endif %}"
|
value="{{ form.min_order_amount.value|format_decimal:2|default_if_none:'' }}"
|
||||||
step="0.01" min="0">
|
step="0.01" min="0">
|
||||||
<div class="form-text">Для скидок на заказ</div>
|
<div class="form-text">Для скидок на заказ</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_max_usage_count" class="form-label">Макс. использований</label>
|
<label for="id_max_usage_count" class="form-label">Макс. использований</label>
|
||||||
<input type="number" class="form-control" id="id_max_usage_count" name="max_usage_count"
|
<input type="number" class="form-control" id="id_max_usage_count" name="max_usage_count"
|
||||||
value="{% if form.instance.pk %}{{ form.instance.max_usage_count|default_if_none:'' }}{% else %}{{ form.max_usage_count.value|default_if_none:'' }}{% endif %}"
|
value="{{ form.max_usage_count.value|default_if_none:'' }}"
|
||||||
min="1">
|
min="1">
|
||||||
<div class="form-text">Оставьте пустым для безлимитного использования</div>
|
<div class="form-text">Оставьте пустым для безлимитного использования</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -148,12 +149,12 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_start_date" class="form-label">Дата начала</label>
|
<label for="id_start_date" class="form-label">Дата начала</label>
|
||||||
<input type="datetime-local" class="form-control" id="id_start_date" name="start_date"
|
<input type="datetime-local" class="form-control" id="id_start_date" name="start_date"
|
||||||
value="{% if form.instance.pk and form.instance.start_date %}{{ form.instance.start_date|date:'Y-m-d\TH:i' }}{% elif form.start_date.value %}{{ form.start_date.value|date:'Y-m-d\TH:i' }}{% endif %}">
|
value="{{ form.start_date.value|date:'Y-m-d\TH:i'|default_if_none:'' }}">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="id_end_date" class="form-label">Дата окончания</label>
|
<label for="id_end_date" class="form-label">Дата окончания</label>
|
||||||
<input type="datetime-local" class="form-control" id="id_end_date" name="end_date"
|
<input type="datetime-local" class="form-control" id="id_end_date" name="end_date"
|
||||||
value="{% if form.instance.pk and form.instance.end_date %}{{ form.instance.end_date|date:'Y-m-d\TH:i' }}{% elif form.end_date.value %}{{ form.end_date.value|date:'Y-m-d\TH:i' }}{% endif %}">
|
value="{{ form.end_date.value|date:'Y-m-d\TH:i'|default_if_none:'' }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -211,4 +212,46 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Заменяем запятые на точки в числовых полях при загрузке страницы
|
||||||
|
const numberInputs = document.querySelectorAll('input[type="number"]');
|
||||||
|
numberInputs.forEach(function(input) {
|
||||||
|
if (input.value && input.value.includes(',')) {
|
||||||
|
// Сохраняем оригинальное значение с запятой для отображения
|
||||||
|
const displayValue = input.value;
|
||||||
|
const actualValue = displayValue.replace(',', '.');
|
||||||
|
|
||||||
|
// Устанавливаем значение с точкой для корректной работы HTML5 поля
|
||||||
|
input.value = actualValue;
|
||||||
|
|
||||||
|
// При фокусе возвращаем запятую для удобства пользователя
|
||||||
|
input.addEventListener('focus', function() {
|
||||||
|
if (input.value && input.value.includes('.')) {
|
||||||
|
input.value = input.value.replace('.', ',');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// При потере фокуса возвращаем точку для корректной отправки
|
||||||
|
input.addEventListener('blur', function() {
|
||||||
|
if (input.value && input.value.includes(',')) {
|
||||||
|
input.value = input.value.replace(',', '.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Также обрабатываем отправку формы для замены запятых на точки
|
||||||
|
const form = document.querySelector('form');
|
||||||
|
form.addEventListener('submit', function() {
|
||||||
|
const numberInputs = document.querySelectorAll('input[type="number"]');
|
||||||
|
numberInputs.forEach(function(input) {
|
||||||
|
if (input.value && input.value.includes(',')) {
|
||||||
|
input.value = input.value.replace(',', '.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load inventory_filters %}
|
||||||
|
|
||||||
{% block title %}Заказ {{ order.order_number }}{% endblock %}
|
{% block title %}Заказ {{ order.order_number }}{% endblock %}
|
||||||
|
|
||||||
@@ -337,7 +338,7 @@
|
|||||||
<!-- Кнопка "Применить максимум" -->
|
<!-- Кнопка "Применить максимум" -->
|
||||||
<form method="post" action="{% url 'orders:apply-wallet' order.order_number %}" class="mb-2">
|
<form method="post" action="{% url 'orders:apply-wallet' order.order_number %}" class="mb-2">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="wallet_amount" value="{% if order.customer.wallet_balance < order.amount_due %}{{ order.customer.wallet_balance|floatformat:2 }}{% else %}{{ order.amount_due|floatformat:2 }}{% endif %}">
|
<input type="hidden" name="wallet_amount" value="{% if order.customer.wallet_balance < order.amount_due %}{{ order.customer.wallet_balance|format_decimal:2 }}{% else %}{{ order.amount_due|format_decimal:2 }}{% endif %}">
|
||||||
<button type="submit" class="btn btn-success w-100">
|
<button type="submit" class="btn btn-success w-100">
|
||||||
<i class="bi bi-wallet2"></i> Применить максимум
|
<i class="bi bi-wallet2"></i> Применить максимум
|
||||||
</button>
|
</button>
|
||||||
@@ -351,7 +352,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
min="0"
|
min="0"
|
||||||
max="{% if order.customer.wallet_balance < order.amount_due %}{{ order.customer.wallet_balance|floatformat:2 }}{% else %}{{ order.amount_due|floatformat:2 }}{% endif %}"
|
max="{% if order.customer.wallet_balance < order.amount_due %}{{ order.customer.wallet_balance|format_decimal:2 }}{% else %}{{ order.amount_due|format_decimal:2 }}{% endif %}"
|
||||||
name="wallet_amount"
|
name="wallet_amount"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
placeholder="Сумма"
|
placeholder="Сумма"
|
||||||
|
|||||||
Reference in New Issue
Block a user