Запрет редактирования приходов после создания складской партии

- Добавлено свойство can_edit в модель Incoming
- Добавлена проверка в IncomingUpdateView для запрета редактирования обработанных приходов
- Скрыта кнопка редактирования в списке приходов для обработанных записей
- Добавлено предупреждение в форму редактирования

Это предотвращает проблемы с целостностью данных при FIFO-списаниях, когда партия уже может быть использована в продажах.
This commit is contained in:
2025-12-25 23:01:12 +03:00
parent bc13750d16
commit 131d078ac4
4 changed files with 35 additions and 4 deletions

View File

@@ -174,6 +174,11 @@ class Incoming(models.Model):
def __str__(self):
return f"{self.product.name}: {self.quantity} шт (партия {self.batch.document_number})"
@property
def can_edit(self):
"""Можно ли редактировать приход"""
return self.stock_batch is None
class Sale(models.Model):
"""

View File

@@ -23,6 +23,13 @@
</div>
<div class="card-body">
{% if form.instance.pk and not form.instance.can_edit %}
<div class="alert alert-warning" role="alert">
<i class="bi bi-exclamation-triangle"></i>
<strong>Внимание!</strong> Этот приход товара уже обработан (для него создана складская партия).
Редактирование недоступно, так как партия может быть использована в продажах.
</div>
{% endif %}
<form method="post" class="form">
{% csrf_token %}

View File

@@ -60,9 +60,15 @@
</td>
<td>{{ incoming.created_at|date:"d.m.Y H:i" }}</td>
<td class="text-end">
<a href="{% url 'inventory:incoming-update' incoming.pk %}" class="btn btn-sm btn-outline-primary">
{% if incoming.can_edit %}
<a href="{% url 'inventory:incoming-update' incoming.pk %}" class="btn btn-sm btn-outline-primary" title="Редактировать приход">
<i class="bi bi-pencil"></i>
</a>
{% else %}
<span class="btn btn-sm btn-outline-secondary disabled" title="Редактирование недоступно: приход уже обработан">
<i class="bi bi-pencil"></i>
</span>
{% endif %}
<a href="{% url 'inventory:incoming-delete' incoming.pk %}" class="btn btn-sm btn-outline-danger">
<i class="bi bi-trash"></i>
</a>

View File

@@ -5,7 +5,7 @@ from django.views.generic import ListView, CreateView, UpdateView, DeleteView, V
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib import messages
from django.http import JsonResponse
from django.http import JsonResponse, Http404
from django.views.decorators.http import require_http_methods
from django.utils.decorators import method_decorator
from django.db import IntegrityError, transaction
@@ -51,6 +51,19 @@ class IncomingUpdateView(LoginRequiredMixin, UpdateView):
template_name = 'inventory/incoming/incoming_form.html'
success_url = reverse_lazy('inventory:incoming-list')
def dispatch(self, request, *args, **kwargs):
"""Проверяем, можно ли редактировать приход"""
obj = self.get_object()
if not obj.can_edit:
messages.error(
request,
f'Нельзя редактировать приход товара "{obj.product.name}", '
f'так как для него уже создана складская партия. '
f'Редактирование возможно только до обработки прихода.'
)
return redirect('inventory:incoming-list')
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
messages.success(self.request, f'Приход товара обновлён.')
return super().form_valid(form)