Files
octopus/myproject/orders/templates/orders/status_form.html
Andrey Smakotin 2aba3d2404 Улучшения в тестах переходов статусов заказов
- Исправлены комментарии и форматирование в signals.py
- Улучшена читаемость кода в models.py
- Обновлены шаблоны форм статусов
- Доработаны тесты переходов статусов
2026-01-05 21:30:25 +03:00

317 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% load static %}
{% block title %}{% if form.instance.pk %}Редактировать{% else %}Создать{% endif %} статус{% endblock %}
{% block content %}
<div class="container-fluid mt-4">
<div class="row mb-4">
<div class="col-md-8">
<h1>
{% if form.instance.pk %}
Редактировать статус: {{ form.instance.name }}
{% else %}
Создать новый статус
{% endif %}
</h1>
{% if is_system %}
<div class="alert alert-danger mt-2">
<i class="fas fa-exclamation-triangle"></i>
<strong>ВНИМАНИЕ!</strong> Это системный статус, используемый в бизнес-логике системы.
<ul class="mb-0 mt-2">
<li><strong>Код статуса</strong> — заблокирован (используется в коде для проверок)</li>
<li><strong>Положительный/Отрицательный исход</strong> — заблокированы (управляют резервированием и списанием товаров со склада)</li>
<li>Разрешено изменять: название, метку, цвет и описание</li>
</ul>
</div>
{% endif %}
</div>
<div class="col-md-4 text-end">
<a href="{% url 'orders:status_list' %}" class="btn btn-secondary">
<i class="fas fa-arrow-left"></i> Вернуться к статусам
</a>
</div>
</div>
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
<h4 class="alert-heading">Ошибка!</h4>
{% for error in form.non_field_errors %}
<p>{{ error }}</p>
{% endfor %}
</div>
{% endif %}
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
<form method="post" novalidate>
{% csrf_token %}
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.name.id_for_label }}" class="form-label">
{{ form.name.label }}
<span class="text-danger">*</span>
</label>
{{ form.name }}
{% if form.name.errors %}
<div class="invalid-feedback d-block">
{% for error in form.name.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
<small class="form-text text-muted">
Например: Выполнен, В процессе, Возврат
</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.code.id_for_label }}" class="form-label">
{{ form.code.label }}
<span class="text-danger">*</span>
</label>
{{ form.code }}
{% if form.code.errors %}
<div class="invalid-feedback d-block">
{% for error in form.code.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
<small class="form-text text-muted">
{% if form.code.field.help_text %}
{{ form.code.field.help_text|safe }}
{% else %}
Латинские буквы, цифры и подчеркивания
{% endif %}
</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.label.id_for_label }}" class="form-label">
{{ form.label.label }}
</label>
{{ form.label }}
{% if form.label.errors %}
<div class="invalid-feedback d-block">
{% for error in form.label.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
<small class="form-text text-muted">
Для отображения в интерфейсе (опционально)
</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="{{ form.color.id_for_label }}" class="form-label">
{{ form.color.label }}
</label>
<div class="input-group">
{{ form.color }}
<span class="input-group-text" id="color-preview" style="width: 60px; background-color: #808080;"></span>
</div>
{% if form.color.errors %}
<div class="invalid-feedback d-block">
{% for error in form.color.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label for="{{ form.description.id_for_label }}" class="form-label">
{{ form.description.label }}
</label>
{{ form.description }}
{% if form.description.errors %}
<div class="invalid-feedback d-block">
{% for error in form.description.errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
<small class="form-text text-muted">
Описание для пользователей (опционально)
</small>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-check mb-3">
{{ form.is_positive_end }}
<label class="form-check-label" for="{{ form.is_positive_end.id_for_label }}">
{{ form.is_positive_end.label }}
</label>
<small class="d-block text-muted mt-1">
Отметьте, если это успешный финальный статус (Выполнен)
</small>
</div>
</div>
<div class="col-md-6">
<div class="form-check mb-3">
{{ form.is_negative_end }}
<label class="form-check-label" for="{{ form.is_negative_end.id_for_label }}">
{{ form.is_negative_end.label }}
</label>
<small class="d-block text-muted mt-1">
Отметьте, если это отрицательный финальный статус (Отменен)
</small>
</div>
</div>
</div>
<div class="d-flex gap-2 mt-4">
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i>
{% if form.instance.pk %}
Сохранить изменения
{% else %}
Создать статус
{% endif %}
</button>
<a href="{% url 'orders:status_list' %}" class="btn btn-secondary">
<i class="fas fa-times"></i> Отменить
</a>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header bg-light">
<h6 class="mb-0">Предпросмотр</h6>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Название статуса</label>
<p class="lead">
<span id="preview-name">{{ form.instance.name|default:"Название" }}</span>
</p>
</div>
<div class="mb-3">
<label class="form-label">Код статуса</label>
<code id="preview-code">{{ form.instance.code|default:"код" }}</code>
</div>
<div class="mb-3">
<label class="form-label">Внешний вид</label>
<div style="padding: 10px; border-radius: 4px; background-color: {{ form.instance.color|default:'#808080' }}; color: white; text-align: center;" id="preview-color">
<strong id="preview-color-text">{{ form.instance.name|default:"Статус" }}</strong>
</div>
</div>
<div class="mb-3">
<label class="form-label">Тип статуса</label>
<p id="preview-type">
{% if form.instance.is_system %}
<span class="badge bg-info">Системный</span>
{% else %}
<span class="badge bg-success">Пользовательский</span>
{% endif %}
</p>
</div>
<div class="mb-3">
<label class="form-label">Финальный статус</label>
<p id="preview-end">
{% if form.instance.is_positive_end %}
<span class="badge bg-success">✓ Успешный исход сделки</span>
{% elif form.instance.is_negative_end %}
<span class="badge bg-danger">✗ Отрицательный исход сделки</span>
{% else %}
<span class="badge bg-secondary">Промежуточный</span>
{% endif %}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const nameInput = document.getElementById('{{ form.name.id_for_label }}');
const codeInput = document.getElementById('{{ form.code.id_for_label }}');
const colorInput = document.getElementById('{{ form.color.id_for_label }}');
const positiveEndCheckbox = document.getElementById('{{ form.is_positive_end.id_for_label }}');
const negativeEndCheckbox = document.getElementById('{{ form.is_negative_end.id_for_label }}');
const previewName = document.getElementById('preview-name');
const previewCode = document.getElementById('preview-code');
const previewColor = document.getElementById('preview-color');
const previewColorText = document.getElementById('preview-color-text');
const colorPreview = document.getElementById('color-preview');
const previewEnd = document.getElementById('preview-end');
function updatePreview() {
// Обновляем название
previewName.textContent = nameInput.value || 'Название';
previewColorText.textContent = nameInput.value || 'Статус';
// Обновляем код
previewCode.textContent = codeInput.value || 'код';
// Обновляем цвет
const color = colorInput.value || '#808080';
previewColor.style.backgroundColor = color;
colorPreview.style.backgroundColor = color;
// Обновляем тип конца
if (positiveEndCheckbox.checked) {
previewEnd.innerHTML = '<span class="badge bg-success">✓ Успешный исход сделки</span>';
} else if (negativeEndCheckbox.checked) {
previewEnd.innerHTML = '<span class="badge bg-danger">✗ Отрицательный исход сделки</span>';
} else {
previewEnd.innerHTML = '<span class="badge bg-secondary">Промежуточный</span>';
}
}
nameInput.addEventListener('input', updatePreview);
codeInput.addEventListener('input', updatePreview);
colorInput.addEventListener('change', updatePreview);
positiveEndCheckbox.addEventListener('change', updatePreview);
negativeEndCheckbox.addEventListener('change', updatePreview);
// Взаимное отключение чекбоксов: нельзя быть одновременно положительным и отрицательным
positiveEndCheckbox.addEventListener('change', function() {
if (this.checked) {
negativeEndCheckbox.checked = false;
}
updatePreview();
});
negativeEndCheckbox.addEventListener('change', function() {
if (this.checked) {
positiveEndCheckbox.checked = false;
}
updatePreview();
});
// Инициальное обновление
updatePreview();
});
</script>
{% endblock %}