refactor: стандартизация моделей документов перемещения
Приведение к единому паттерну именования документов: - TransferBatch → TransferDocument - TransferItem → TransferDocumentItem - Удалена устаревшая модель Transfer (одиночные перемещения) - Удалена неиспользуемая модель StockMovement Изменения: - models.py: переименование классов, обновление related_names - admin.py: удаление регистраций Transfer/StockMovement - forms.py: обновление TransferHeaderForm - views/transfer.py: обновление всех view классов - templates: замена transfer_batch → transfer_document - urls.py: удаление путей для movements - views/__init__.py: удаление импорта StockMovementListView - views/movements.py: удален файл Миграция: 0005_refactor_transfer_models - RenameModel операции для сохранения данных - DeleteModel для Transfer и StockMovement Единый паттерн: *Document + *DocumentItem (WriteOffDocument, IncomingDocument, TransferDocument) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,11 +5,11 @@ from django.db.models import Sum
|
||||
from decimal import Decimal
|
||||
|
||||
from inventory.models import (
|
||||
Warehouse, StockBatch, Sale, WriteOff, Transfer,
|
||||
Inventory, InventoryLine, Reservation, Stock, StockMovement,
|
||||
Warehouse, StockBatch, Sale, WriteOff,
|
||||
Inventory, InventoryLine, Reservation, Stock,
|
||||
SaleBatchAllocation, Showcase, WriteOffDocument, WriteOffDocumentItem,
|
||||
IncomingDocument, IncomingDocumentItem, Transformation, TransformationInput,
|
||||
TransformationOutput
|
||||
TransformationOutput, TransferDocument, TransferDocumentItem
|
||||
)
|
||||
|
||||
|
||||
@@ -166,28 +166,6 @@ class WriteOffAdmin(admin.ModelAdmin):
|
||||
reason_display.short_description = 'Причина'
|
||||
|
||||
|
||||
# ===== TRANSFER =====
|
||||
@admin.register(Transfer)
|
||||
class TransferAdmin(admin.ModelAdmin):
|
||||
list_display = ('batch', 'from_warehouse', 'to_warehouse', 'quantity', 'date')
|
||||
list_filter = ('date', 'from_warehouse', 'to_warehouse')
|
||||
search_fields = ('batch__product__name', 'document_number')
|
||||
date_hierarchy = 'date'
|
||||
fieldsets = (
|
||||
('Перемещение', {
|
||||
'fields': ('batch', 'from_warehouse', 'to_warehouse', 'quantity', 'new_batch')
|
||||
}),
|
||||
('Документ', {
|
||||
'fields': ('document_number',)
|
||||
}),
|
||||
('Дата', {
|
||||
'fields': ('date',),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
readonly_fields = ('date', 'new_batch')
|
||||
|
||||
|
||||
# ===== INVENTORY LINE (INLINE) =====
|
||||
class InventoryLineInline(admin.TabularInline):
|
||||
model = InventoryLine
|
||||
@@ -317,16 +295,6 @@ class StockAdmin(admin.ModelAdmin):
|
||||
readonly_fields = ('quantity_available', 'quantity_reserved', 'updated_at')
|
||||
|
||||
|
||||
# ===== STOCK MOVEMENT (для аудита) =====
|
||||
@admin.register(StockMovement)
|
||||
class StockMovementAdmin(admin.ModelAdmin):
|
||||
list_display = ('product', 'change', 'reason', 'order', 'created_at')
|
||||
list_filter = ('reason', 'created_at')
|
||||
search_fields = ('product__name', 'order__order_number')
|
||||
date_hierarchy = 'created_at'
|
||||
readonly_fields = ('created_at',)
|
||||
|
||||
|
||||
# ===== WRITEOFF DOCUMENT (документы списания) =====
|
||||
class WriteOffDocumentItemInline(admin.TabularInline):
|
||||
model = WriteOffDocumentItem
|
||||
|
||||
@@ -4,8 +4,8 @@ from django.core.exceptions import ValidationError
|
||||
from decimal import Decimal
|
||||
|
||||
from .models import (
|
||||
Warehouse, Sale, WriteOff, Transfer, Reservation, Inventory, InventoryLine, StockBatch,
|
||||
TransferBatch, TransferItem, Showcase, WriteOffDocument, WriteOffDocumentItem, Stock,
|
||||
Warehouse, Sale, WriteOff, Reservation, Inventory, InventoryLine, StockBatch,
|
||||
TransferDocument, TransferDocumentItem, Showcase, WriteOffDocument, WriteOffDocumentItem, Stock,
|
||||
IncomingDocument, IncomingDocumentItem, Transformation, TransformationInput, TransformationOutput
|
||||
)
|
||||
from products.models import Product
|
||||
@@ -157,7 +157,7 @@ class TransferHeaderForm(forms.ModelForm):
|
||||
Содержит информацию о складах-источнике и складе-назначении, примечания.
|
||||
"""
|
||||
class Meta:
|
||||
model = TransferBatch
|
||||
model = TransferDocument
|
||||
fields = ['from_warehouse', 'to_warehouse', 'notes']
|
||||
widgets = {
|
||||
'from_warehouse': forms.Select(attrs={'class': 'form-control'}),
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generated migration for Transfer models refactoring
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('inventory', '0004_remove_incoming_batch_and_incoming'),
|
||||
('products', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# 1. Удаление устаревших моделей ПЕРЕД переименованием
|
||||
migrations.DeleteModel(
|
||||
name='Transfer',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='StockMovement',
|
||||
),
|
||||
|
||||
# 2. Переименование моделей
|
||||
migrations.RenameModel(
|
||||
old_name='TransferBatch',
|
||||
new_name='TransferDocument',
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name='TransferItem',
|
||||
new_name='TransferDocumentItem',
|
||||
),
|
||||
|
||||
# 3. Переименование поля transfer_batch → transfer_document в TransferDocumentItem
|
||||
migrations.RenameField(
|
||||
model_name='transferdocumentitem',
|
||||
old_name='transfer_batch',
|
||||
new_name='transfer_document',
|
||||
),
|
||||
]
|
||||
@@ -215,35 +215,6 @@ class WriteOff(models.Model):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class Transfer(models.Model):
|
||||
"""
|
||||
Перемещение товара между складами. Сохраняет партийность.
|
||||
"""
|
||||
batch = models.ForeignKey(StockBatch, on_delete=models.CASCADE,
|
||||
related_name='transfers', verbose_name="Партия")
|
||||
from_warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE,
|
||||
related_name='transfers_from', verbose_name="Из склада")
|
||||
to_warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE,
|
||||
related_name='transfers_to', verbose_name="На склад")
|
||||
quantity = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Количество")
|
||||
document_number = models.CharField(max_length=100, blank=True, null=True,
|
||||
verbose_name="Номер документа")
|
||||
date = models.DateTimeField(auto_now_add=True, verbose_name="Дата операции")
|
||||
new_batch = models.ForeignKey(StockBatch, on_delete=models.SET_NULL, null=True, blank=True,
|
||||
related_name='transfer_sources', verbose_name="Новая партия")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Перемещение"
|
||||
verbose_name_plural = "Перемещения"
|
||||
ordering = ['-date']
|
||||
indexes = [
|
||||
models.Index(fields=['from_warehouse', 'to_warehouse']),
|
||||
models.Index(fields=['date']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"Перемещение {self.batch.product.name} ({self.quantity} шт): {self.from_warehouse} → {self.to_warehouse}"
|
||||
|
||||
|
||||
class Inventory(models.Model):
|
||||
"""
|
||||
@@ -731,38 +702,6 @@ class Stock(models.Model):
|
||||
self.save()
|
||||
|
||||
|
||||
class StockMovement(models.Model):
|
||||
"""
|
||||
Журнал всех складских операций (приход, списание, коррекция).
|
||||
Используется для аудита.
|
||||
"""
|
||||
REASON_CHOICES = [
|
||||
('purchase', 'Закупка'),
|
||||
('sale', 'Продажа'),
|
||||
('write_off', 'Списание'),
|
||||
('adjustment', 'Корректировка'),
|
||||
]
|
||||
|
||||
product = models.ForeignKey(Product, on_delete=models.CASCADE,
|
||||
related_name='movements', verbose_name="Товар")
|
||||
change = models.DecimalField(max_digits=10, decimal_places=3, verbose_name="Изменение")
|
||||
reason = models.CharField(max_length=20, choices=REASON_CHOICES, verbose_name="Причина")
|
||||
order = models.ForeignKey('orders.Order', on_delete=models.SET_NULL, null=True, blank=True,
|
||||
related_name='stock_movements', verbose_name="Заказ")
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Движение товара"
|
||||
verbose_name_plural = "Движения товаров"
|
||||
indexes = [
|
||||
models.Index(fields=['product']),
|
||||
models.Index(fields=['created_at']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.product.name}: {self.change} ({self.reason})"
|
||||
|
||||
|
||||
class DocumentCounter(models.Model):
|
||||
"""
|
||||
Счетчик номеров документов для различных операций.
|
||||
@@ -811,7 +750,7 @@ class DocumentCounter(models.Model):
|
||||
return obj.current_value
|
||||
|
||||
|
||||
class TransferBatch(models.Model):
|
||||
class TransferDocument(models.Model):
|
||||
"""
|
||||
Документ перемещения товара между складами.
|
||||
Один номер документа = одна операция перемещения множественных товаров.
|
||||
@@ -819,13 +758,13 @@ class TransferBatch(models.Model):
|
||||
from_warehouse = models.ForeignKey(
|
||||
Warehouse,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='transfer_batches_from',
|
||||
related_name='transfer_documents_from',
|
||||
verbose_name="Склад-отгрузки"
|
||||
)
|
||||
to_warehouse = models.ForeignKey(
|
||||
Warehouse,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='transfer_batches_to',
|
||||
related_name='transfer_documents_to',
|
||||
verbose_name="Склад-приемки"
|
||||
)
|
||||
document_number = models.CharField(
|
||||
@@ -866,13 +805,13 @@ class TransferBatch(models.Model):
|
||||
return f"Перемещение {self.document_number}: {total_items} товаров, {total_qty} шт ({self.from_warehouse} → {self.to_warehouse})"
|
||||
|
||||
|
||||
class TransferItem(models.Model):
|
||||
class TransferDocumentItem(models.Model):
|
||||
"""
|
||||
Строка документа перемещения (товар в перемещении).
|
||||
Связь между документом и товарами.
|
||||
"""
|
||||
transfer_batch = models.ForeignKey(
|
||||
TransferBatch,
|
||||
transfer_document = models.ForeignKey(
|
||||
TransferDocument,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='items',
|
||||
verbose_name="Документ перемещения"
|
||||
@@ -880,13 +819,13 @@ class TransferItem(models.Model):
|
||||
product = models.ForeignKey(
|
||||
Product,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='transfer_items',
|
||||
related_name='transfer_document_items',
|
||||
verbose_name="Товар"
|
||||
)
|
||||
batch = models.ForeignKey(
|
||||
StockBatch,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='transfer_items',
|
||||
related_name='transfer_document_items',
|
||||
verbose_name="Исходная партия (FIFO)"
|
||||
)
|
||||
quantity = models.DecimalField(
|
||||
@@ -899,17 +838,17 @@ class TransferItem(models.Model):
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name='transfer_items_created',
|
||||
related_name='transfer_document_items_created',
|
||||
verbose_name="Созданная партия на целевом складе"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Строка перемещения"
|
||||
verbose_name_plural = "Строки перемещения"
|
||||
unique_together = [['transfer_batch', 'batch']]
|
||||
unique_together = [['transfer_document', 'batch']]
|
||||
ordering = ['id']
|
||||
indexes = [
|
||||
models.Index(fields=['transfer_batch']),
|
||||
models.Index(fields=['transfer_document']),
|
||||
models.Index(fields=['product']),
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Документ перемещения {{ transfer_batch.document_number }}{% endblock %}
|
||||
{% block title %}Документ перемещения {{ transfer_document.document_number }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid px-4 py-3">
|
||||
@@ -8,7 +8,7 @@
|
||||
<nav aria-label="breadcrumb" class="mb-2">
|
||||
<ol class="breadcrumb breadcrumb-sm mb-0">
|
||||
<li class="breadcrumb-item"><a href="{% url 'inventory:transfer-list' %}">Перемещения</a></li>
|
||||
<li class="breadcrumb-item active">{{ transfer_batch.document_number }}</li>
|
||||
<li class="breadcrumb-item active">{{ transfer_document.document_number }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
@@ -18,36 +18,36 @@
|
||||
<div class="card border-0 shadow-sm mb-3">
|
||||
<div class="card-header bg-light py-3">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-arrow-left-right me-2"></i>{{ transfer_batch.document_number }}
|
||||
<i class="bi bi-arrow-left-right me-2"></i>{{ transfer_document.document_number }}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted small mb-1">Склад-отгрузки</p>
|
||||
<p class="fw-semibold">{{ transfer_batch.from_warehouse.name }}</p>
|
||||
<p class="fw-semibold">{{ transfer_document.from_warehouse.name }}</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted small mb-1">Склад-приемки</p>
|
||||
<p class="fw-semibold">{{ transfer_batch.to_warehouse.name }}</p>
|
||||
<p class="fw-semibold">{{ transfer_document.to_warehouse.name }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if transfer_batch.notes %}
|
||||
{% if transfer_document.notes %}
|
||||
<div class="mb-3">
|
||||
<p class="text-muted small mb-1">Примечания</p>
|
||||
<p>{{ transfer_batch.notes }}</p>
|
||||
<p>{{ transfer_document.notes }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted small mb-1">Дата создания</p>
|
||||
<p class="fw-semibold">{{ transfer_batch.created_at|date:"d.m.Y H:i" }}</p>
|
||||
<p class="fw-semibold">{{ transfer_document.created_at|date:"d.m.Y H:i" }}</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p class="text-muted small mb-1">Последнее обновление</p>
|
||||
<p class="fw-semibold">{{ transfer_batch.updated_at|date:"d.m.Y H:i" }}</p>
|
||||
<p class="fw-semibold">{{ transfer_document.updated_at|date:"d.m.Y H:i" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,7 +132,7 @@
|
||||
<a href="{% url 'inventory:transfer-list' %}" class="btn btn-outline-secondary btn-sm">
|
||||
<i class="bi bi-arrow-left me-1"></i>Вернуться к списку
|
||||
</a>
|
||||
<a href="{% url 'inventory:transfer-delete' transfer_batch.id %}" class="btn btn-outline-danger btn-sm">
|
||||
<a href="{% url 'inventory:transfer-delete' transfer_document.id %}" class="btn btn-outline-danger btn-sm">
|
||||
<i class="bi bi-trash me-1"></i>Удалить
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -21,8 +21,6 @@ from .views import (
|
||||
StockBatchListView, StockBatchDetailView,
|
||||
# SaleBatchAllocation
|
||||
SaleBatchAllocationListView,
|
||||
# StockMovement
|
||||
StockMovementListView,
|
||||
)
|
||||
# Showcase views
|
||||
from .views.showcase import ShowcaseListView, ShowcaseCreateView, ShowcaseUpdateView, ShowcaseDeleteView, SetDefaultShowcaseView
|
||||
@@ -131,9 +129,6 @@ urlpatterns = [
|
||||
# ==================== ALLOCATION (READ ONLY) ====================
|
||||
path('allocations/', SaleBatchAllocationListView.as_view(), name='allocation-list'),
|
||||
|
||||
# ==================== MOVEMENT (READ ONLY) ====================
|
||||
path('movements/', StockMovementListView.as_view(), name='movement-list'),
|
||||
|
||||
# ==================== SHOWCASE ====================
|
||||
path('showcases/', ShowcaseListView.as_view(), name='showcase-list'),
|
||||
path('showcases/create/', ShowcaseCreateView.as_view(), name='showcase-create'),
|
||||
|
||||
@@ -13,7 +13,6 @@ Inventory Views Package
|
||||
- stock.py: Справочник остатков (view-only)
|
||||
- batch.py: Справочник партий товара (view-only)
|
||||
- allocation.py: Распределение продаж по партиям (view-only)
|
||||
- movements.py: Журнал складских операций (view-only)
|
||||
"""
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.decorators import login_required
|
||||
@@ -41,7 +40,6 @@ from .transfer import TransferListView, TransferBulkCreateView, TransferDetailVi
|
||||
from .reservation import ReservationListView
|
||||
from .stock import StockListView, StockDetailView
|
||||
from .allocation import SaleBatchAllocationListView
|
||||
from .movements import StockMovementListView
|
||||
|
||||
|
||||
@login_required
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
StockMovement (Журнал всех складских операций) views - READ ONLY
|
||||
GROUP 3: LOW PRIORITY - Аудит логирование
|
||||
"""
|
||||
from django.views.generic import ListView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from ..models import StockMovement
|
||||
|
||||
|
||||
class StockMovementListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
Полный журнал всех складских операций (приход, продажа, списание, корректировка).
|
||||
Используется для аудита и контроля.
|
||||
"""
|
||||
model = StockMovement
|
||||
template_name = 'inventory/movements/movement_list.html'
|
||||
context_object_name = 'movements'
|
||||
paginate_by = 50
|
||||
|
||||
def get_queryset(self):
|
||||
return StockMovement.objects.select_related(
|
||||
'product', 'order'
|
||||
).order_by('-created_at')
|
||||
@@ -13,7 +13,7 @@ from django.contrib import messages
|
||||
from django.http import JsonResponse
|
||||
from django.db import transaction
|
||||
from django.shortcuts import redirect, render
|
||||
from ..models import TransferBatch, TransferItem, Stock
|
||||
from ..models import TransferDocument, TransferDocumentItem, Stock
|
||||
from ..forms import TransferBulkForm
|
||||
from inventory.utils.document_generator import generate_transfer_document_number
|
||||
from inventory.services.batch_manager import StockBatchManager
|
||||
@@ -24,19 +24,19 @@ class TransferListView(LoginRequiredMixin, ListView):
|
||||
"""
|
||||
View для просмотра списка документов перемещений товаров.
|
||||
"""
|
||||
model = TransferBatch
|
||||
model = TransferDocument
|
||||
template_name = 'inventory/transfer/transfer_list.html'
|
||||
context_object_name = 'transfers'
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
return TransferBatch.objects.select_related(
|
||||
return TransferDocument.objects.select_related(
|
||||
'from_warehouse', 'to_warehouse'
|
||||
).order_by('-created_at')
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# VIEWS ДЛЯ ПЕРЕМЕЩЕНИЯ ТОВАРОВ (TransferBatch + TransferItem)
|
||||
# VIEWS ДЛЯ ПЕРЕМЕЩЕНИЯ ТОВАРОВ (TransferDocument + TransferDocumentItem)
|
||||
# ============================================================================
|
||||
|
||||
class TransferBulkCreateView(LoginRequiredMixin, View):
|
||||
@@ -100,8 +100,8 @@ class TransferBulkCreateView(LoginRequiredMixin, View):
|
||||
# Начинаем транзакцию
|
||||
try:
|
||||
with transaction.atomic():
|
||||
# 1. Создаем документ TransferBatch
|
||||
transfer_batch = TransferBatch.objects.create(
|
||||
# 1. Создаем документ TransferDocument
|
||||
transfer_document = TransferDocument.objects.create(
|
||||
from_warehouse=from_warehouse,
|
||||
to_warehouse=to_warehouse,
|
||||
document_number=generate_transfer_document_number(),
|
||||
@@ -119,10 +119,10 @@ class TransferBulkCreateView(LoginRequiredMixin, View):
|
||||
quantity=quantity
|
||||
)
|
||||
|
||||
# Создаем TransferItem для каждого использованного batch
|
||||
# Создаем TransferDocumentItem для каждого использованного batch
|
||||
for source_batch, qty_transferred, new_batch in transfers:
|
||||
TransferItem.objects.create(
|
||||
transfer_batch=transfer_batch,
|
||||
TransferDocumentItem.objects.create(
|
||||
transfer_document=transfer_document,
|
||||
product=product,
|
||||
batch=source_batch,
|
||||
quantity=qty_transferred,
|
||||
@@ -136,11 +136,11 @@ class TransferBulkCreateView(LoginRequiredMixin, View):
|
||||
# 3. Успешно создали документ
|
||||
messages.success(
|
||||
request,
|
||||
f'Документ перемещения {transfer_batch.document_number} успешно создан. '
|
||||
f'Документ перемещения {transfer_document.document_number} успешно создан. '
|
||||
f'Перемещено {len(products)} видов товаров.'
|
||||
)
|
||||
|
||||
return redirect('inventory:transfer-detail', pk=transfer_batch.id)
|
||||
return redirect('inventory:transfer-detail', pk=transfer_document.id)
|
||||
|
||||
except Exception as e:
|
||||
messages.error(request, f'Ошибка при создании документа перемещения: {str(e)}')
|
||||
@@ -151,12 +151,12 @@ class TransferDetailView(LoginRequiredMixin, DetailView):
|
||||
"""
|
||||
View для просмотра деталей документа перемещения.
|
||||
"""
|
||||
model = TransferBatch
|
||||
model = TransferDocument
|
||||
template_name = 'inventory/transfer/transfer_detail.html'
|
||||
context_object_name = 'transfer_batch'
|
||||
context_object_name = 'transfer_document'
|
||||
|
||||
def get_queryset(self):
|
||||
return TransferBatch.objects.select_related(
|
||||
return TransferDocument.objects.select_related(
|
||||
'from_warehouse', 'to_warehouse'
|
||||
).prefetch_related(
|
||||
'items__product', 'items__batch', 'items__new_batch'
|
||||
@@ -164,10 +164,10 @@ class TransferDetailView(LoginRequiredMixin, DetailView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
transfer_batch = self.object
|
||||
transfer_document = self.object
|
||||
|
||||
# Собираем статистику по документу
|
||||
items = transfer_batch.items.all()
|
||||
items = transfer_document.items.all()
|
||||
total_items = items.count()
|
||||
total_qty = sum(Decimal(str(item.quantity)) for item in items)
|
||||
|
||||
@@ -182,13 +182,13 @@ class TransferDeleteView(LoginRequiredMixin, DeleteView):
|
||||
"""
|
||||
View для удаления документа перемещения.
|
||||
"""
|
||||
model = TransferBatch
|
||||
model = TransferDocument
|
||||
template_name = 'inventory/transfer/transfer_confirm_delete.html'
|
||||
success_url = reverse_lazy('inventory:transfer-list')
|
||||
|
||||
def form_valid(self, form):
|
||||
transfer_batch = self.get_object()
|
||||
messages.success(self.request, f'Документ перемещения {transfer_batch.document_number} удалён.')
|
||||
transfer_document = self.get_object()
|
||||
messages.success(self.request, f'Документ перемещения {transfer_document.document_number} удалён.')
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user