from django.contrib import admin, messages from django.utils import timezone from warehouse.services.transfers import receive_transfer from .models import Location, Material, MaterialCategory, SteelGrade, StockItem, TransferLine, TransferRecord @admin.register(MaterialCategory) class MaterialCategoryAdmin(admin.ModelAdmin): list_display = ('name', 'form_factor', 'gost_standard') list_filter = ('form_factor',) search_fields = ('name', 'gost_standard') @admin.register(SteelGrade) class SteelGradeAdmin(admin.ModelAdmin): list_display = ('name', 'gost_standard') search_fields = ('name', 'gost_standard') @admin.register(Material) class MaterialAdmin(admin.ModelAdmin): list_display = ('full_name', 'category', 'steel_grade', 'name') list_filter = ('category', 'steel_grade') search_fields = ('name', 'full_name') readonly_fields = ('full_name',) @admin.register(Location) class LocationAdmin(admin.ModelAdmin): list_display = ('name', 'is_production_area') list_filter = ('is_production_area',) search_fields = ('name',) @admin.register(StockItem) class StockItemAdmin(admin.ModelAdmin): list_display = ('location', 'material', 'entity', 'quantity', 'is_remnant', 'unique_id') list_filter = ('location', 'is_remnant', 'material__category') search_fields = ('material__name', 'material__full_name', 'entity__name', 'entity__drawing_number', 'unique_id') autocomplete_fields = ('location', 'material', 'entity') class TransferLineInline(admin.TabularInline): model = TransferLine fk_name = 'transfer' fields = ('stock_item', 'quantity') autocomplete_fields = ('stock_item',) extra = 5 def formfield_for_foreignkey(self, db_field, request, **kwargs): if db_field.name == 'stock_item': from_location_id = None tr = getattr(request, '_transfer_obj', None) if tr and getattr(tr, 'from_location_id', None): from_location_id = tr.from_location_id if not from_location_id and request.method == 'POST': raw = (request.POST.get('from_location') or '').strip() if raw.isdigit(): from_location_id = int(raw) if from_location_id: kwargs['queryset'] = StockItem.objects.filter(location_id=from_location_id) else: kwargs['queryset'] = StockItem.objects.all() return super().formfield_for_foreignkey(db_field, request, **kwargs) @admin.register(TransferRecord) class TransferRecordAdmin(admin.ModelAdmin): list_display = ('from_location', 'to_location', 'id', 'occurred_at', 'sender', 'receiver', 'status', 'is_applied') list_display_links = ('from_location',) list_filter = ('status', 'from_location', 'to_location') search_fields = ('sender__username', 'receiver__username') autocomplete_fields = ('from_location', 'to_location', 'sender', 'receiver') inlines = (TransferLineInline,) actions = ('action_receive',) def get_changeform_initial_data(self, request): initial = super().get_changeform_initial_data(request) initial.setdefault('sender', request.user.id) initial.setdefault('occurred_at', timezone.now()) return initial def get_form(self, request, obj=None, **kwargs): request._transfer_obj = obj return super().get_form(request, obj, **kwargs) def save_model(self, request, obj, form, change): if not obj.sender_id: obj.sender = request.user super().save_model(request, obj, form, change) def save_related(self, request, form, formsets, change): super().save_related(request, form, formsets, change) obj = form.instance # Применяем перемещение автоматически после сохранения строк. # Если строк нет — receive_transfer выбросит понятную ошибку. if not getattr(obj, 'is_applied', False): try: receive_transfer(obj.id, request.user.id) except Exception as e: self.message_user(request, f'Перемещение id={obj.id}: {e}', level=messages.ERROR) @admin.action(description='Принять перемещение') def action_receive(self, request, queryset): ok = 0 failed = 0 for tr in queryset: try: receive_transfer(tr.id, request.user.id) ok += 1 except Exception as e: failed += 1 self.message_user(request, f'Перемещение id={tr.id}: {e}', level=messages.ERROR) if ok: self.message_user(request, f'Применено: {ok}.', level=messages.SUCCESS) if failed: self.message_user(request, f'Ошибок: {failed}.', level=messages.ERROR)