Feat: Автоматическая себестоимость товара (read-only)

- Удалено ручное редактирование себестоимости из формы товара
- Себестоимость теперь рассчитывается автоматически из партий (FIFO)
- Добавлена модель CostPriceHistory для логирования изменений
- Добавлен signal для автоматического логирования изменений cost_price
- Админ-панель: себестоимость read-only с детальной информацией о партиях
- Фронтенд: цены перемещены под название, теги под категории
- Поле cost_price сделано опциональным (default=0) для создания товаров

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-23 23:22:45 +03:00
parent 493b6c212d
commit addc5e0962
9 changed files with 374 additions and 71 deletions

View File

@@ -33,6 +33,26 @@
{% endif %}
</div>
<!-- Основная цена и Цена со скидкой -->
<div class="row mb-3">
<div class="col-md-6">
<label for="id_price" class="form-label fw-bold">Основная цена <span class="text-danger">*</span></label>
{{ form.price }}
<small class="form-text text-muted">Цена продажи товара</small>
{% if form.price.errors %}
<div class="text-danger">{{ form.price.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label for="id_sale_price" class="form-label">Цена со скидкой</label>
{{ form.sale_price }}
<small class="form-text text-muted">Необязательно. Если задана, товар будет продаваться по этой цене</small>
{% if form.sale_price.errors %}
<div class="text-danger">{{ form.sale_price.errors }}</div>
{% endif %}
</div>
</div>
<!-- Артикул -->
<div class="mb-3">
{{ form.sku.label_tag }}
@@ -67,6 +87,20 @@
{% endif %}
</div>
<!-- Теги -->
<div class="mb-3">
{{ form.tags.label_tag }}
<div class="p-3 bg-light rounded">
{{ form.tags }}
</div>
{% if form.tags.help_text %}
<small class="form-text text-muted">{{ form.tags.help_text }}</small>
{% endif %}
{% if form.tags.errors %}
<div class="text-danger">{{ form.tags.errors }}</div>
{% endif %}
</div>
<!-- Описание -->
<div class="mb-3">
{{ form.description.label_tag }}
@@ -89,9 +123,9 @@
{% endif %}
</div>
<!-- Единица измерения и Статус в один ряд -->
<!-- Единица измерения, Основная цена, Цена со скидкой -->
<div class="row mb-3">
<div class="col-md-8">
<div class="col-md-6">
{{ form.unit.label_tag }}
{{ form.unit }}
{% if form.unit.help_text %}
@@ -101,7 +135,7 @@
<div class="text-danger">{{ form.unit.errors }}</div>
{% endif %}
</div>
<div class="col-md-4">
<div class="col-md-6">
{{ form.status.label_tag }}
{{ form.status }}
{% if form.status.help_text %}
@@ -116,45 +150,6 @@
<hr class="my-4">
<!-- Блок 2: Ценообразование -->
<div class="mb-4">
<h5 class="mb-3">Ценообразование</h5>
<div class="row mb-3">
<div class="col-md-6">
<label for="id_cost_price" class="form-label">Себестоимость</label>
{{ form.cost_price }}
{% if form.cost_price.help_text %}
<small class="form-text text-muted">{{ form.cost_price.help_text }}</small>
{% endif %}
{% if form.cost_price.errors %}
<div class="text-danger">{{ form.cost_price.errors }}</div>
{% endif %}
</div>
<div class="col-md-6">
<label for="id_price" class="form-label fw-bold">Основная цена <span class="text-danger">*</span></label>
{{ form.price }}
<small class="form-text text-muted">Цена продажи товара</small>
{% if form.price.errors %}
<div class="text-danger">{{ form.price.errors }}</div>
{% endif %}
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<label for="id_sale_price" class="form-label">Цена со скидкой</label>
{{ form.sale_price }}
<small class="form-text text-muted">Необязательно. Если задана, товар будет продаваться по этой цене (дешевле основной)</small>
{% if form.sale_price.errors %}
<div class="text-danger">{{ form.sale_price.errors }}</div>
{% endif %}
</div>
</div>
</div>
<hr class="my-4">
<!-- Блок 2.5: Информация о наличии (только при редактировании) -->
{% if object %}
<div class="mb-4 p-3 bg-info-light rounded border border-info">
@@ -387,25 +382,6 @@
<hr class="my-4">
<!-- Блок 4: Классификация -->
<div class="mb-4">
<h5 class="mb-3">Классификация</h5>
<!-- Теги -->
<div class="mb-3">
{{ form.tags.label_tag }}
<div class="p-3 bg-light rounded">
{{ form.tags }}
</div>
{% if form.tags.help_text %}
<small class="form-text text-muted">{{ form.tags.help_text }}</small>
{% endif %}
{% if form.tags.errors %}
<div class="text-danger">{{ form.tags.errors }}</div>
{% endif %}
</div>
</div>
<div class="d-flex justify-content-between mt-4 gap-2 flex-wrap">
<div>
<a href="{% url 'products:products-list' %}" class="btn btn-secondary">Отмена</a>