forked from erp-dev/erp
172 lines
5.1 KiB
Python
172 lines
5.1 KiB
Python
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.Inventory)
|
|
class InventoryAdmin(StockAdminBase):
|
|
list_display = (
|
|
'id',
|
|
'product',
|
|
'product_color',
|
|
'warehouse',
|
|
'quantity',
|
|
'num_of_rolls',
|
|
'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('<br>'.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',)
|