from django.contrib import admin from django.contrib.admin import action from django.utils.safestring import mark_safe from . import models, services class StockAdminBase(admin.ModelAdmin): """库存管理基础类,定义通用配置""" def get_list_filter(self, request): result = super().get_list_filter(request) result = list(result) + ['created_at'] return result @admin.register(models.PurchaseOrder) class PurchaseOrderAdmin(admin.ModelAdmin): list_display = ('id', 'supplier', 'order_date', 'total_amount') search_fields = ('supplier__name',) list_filter = ('order_date',) ordering = ('-order_date',) @admin.register(models.Inventory) class InventoryAdmin(StockAdminBase): list_display = ( 'id', 'product', 'product_color', 'warehouse', 'quantity', 'num_of_rolls', 'minimum_quantity', 'frozen_quantity', 'updated_at', ) search_fields = ('product__name', 'warehouse__name') list_filter = ('warehouse',) ordering = ('-updated_at',) @admin.display(description='冻结中数量') def frozen_quantity(self, obj): return services.get_frozen_stock_count( product_id=obj.product_id, warehouse_id=obj.warehouse_id ) @admin.display(description='颜色') def product_color(self, obj): return obj.product.color @admin.register(models.StockSnapshot) class StockSnapshotAdmin(admin.ModelAdmin): list_display = ( 'id', 'product__name', 'warehouse__name', 'delta', 'quantity_before', 'quantity_after', 'stock_change_record', 'created_at', ) search_fields = ('product', 'warehouse', 'stock_change_record__id') list_filter = ('stock_change_record__type',) ordering = ('-created_at', ) def has_add_permission(self, request): # 禁止通过admin界面添加库存快照 return False def has_change_permission(self, request, obj = ...): # 禁止通过admin界面修改库存快照 return False def has_delete_permission(self, request, obj = ...): # 禁止通过admin界面删除库存快照 return True def get_readonly_fields(self, request, obj = ...): # 所有字段均为只读 return [field.name for field in self.model._meta.fields] @admin.register(models.StockChangeDetail) class StockChangeDetailAdmin(admin.ModelAdmin): list_display = ( 'id', 'stock_change_record', 'product', 'quantity', 'direction', 'unit', ) search_fields = ('stock_change_record__id', 'product__name') list_filter = ('stock_change_record', 'stock_change_record__type') ordering = ('-created_at',) @admin.display(description='出入方向') def direction(self, obj): return '入库' if obj.stock_change_record.is_incoming else '出库' @admin.register(models.StockChangeRecord) class StockChangeRecordAdmin(admin.ModelAdmin): list_display = ( 'id', 'type', 'warehouse', 'details', 'source_type', 'source_id', 'num_of_rolls', 'is_finished', 'finished_at', 'created_by', 'created_at', ) search_fields = ('warehouse__name', 'source_id') list_filter = ('type', 'source_type', 'type', 'is_finished', 'created_at') ordering = ('-created_at', '-updated_at') readonly_fields = ('created_by', 'is_finished', 'finished_at') def save_model(self, request, obj: models.StockChangeRecord, form, change): if not change: if obj.is_finished is True: # Prevent setting is_finished to True on creation obj.is_finished = False if not obj.created_by: # 新建记录时,设置创建人 obj.created_by = request.user return super().save_model(request, obj, form, change) @action(description='标记选中的库存变动记录为已完成') def make_selected_stock_changes_completed(self, request, queryset): if queryset.count() > 1: self.message_user(request, '一次只能处理一条库存变动记录。', level='error') return record = queryset.first() services.make_stock_change_completed(record) @admin.display(description='匹数') def num_of_rolls(self, obj: models.StockChangeRecord): return obj.num_of_rolls @admin.display(description='明细概览') def details(self, obj): details = obj.details.all() detail_list = [ f'{detail.product.name}, {detail.quantity}/{detail.get_unit_display()}' for detail in details ] return mark_safe('
'.join(detail_list)) actions = [make_selected_stock_changes_completed] @admin.register(models.StockFreeze) class StockFreezeAdmin(admin.ModelAdmin): list_display = ( 'id', 'product', 'warehouse', 'quantity', 'reason', 'created_at', ) readonly_fields = ( 'frozen_by', 'created_at', 'updated_at', 'cancelled_at', 'cancelled_by', 'completed_at', 'completed_by', 'completed_with', ) search_fields = ('product__name', 'warehouse__name', 'reason') list_filter = ('warehouse', 'created_at') ordering = ('-created_at',)