Files
asset-management/assetapp/models.py
cnbugs a07b390995 fix: 修复资产编辑无法保存的bug
- 恢复Asset模型STATUS_CHOICES定义,状态字段使用下拉选择而非文本输入
- 修复status默认值从中文'在用'改为英文key'in_use',与数据库存储一致
- 编辑表单新增资产面值(asset_value)字段
- excel_utils适配字段类型变更(DecimalField→CharField, DateField→CharField等)
2026-05-26 16:48:01 +08:00

135 line
5.6 KiB
Python

from django.db import models
from django.contrib.auth.models import User
from datetime import date
class Category(models.Model):
"""设备分类"""
name = models.CharField('分类名称', max_length=50, unique=True)
description = models.CharField('描述', max_length=200, blank=True, default='')
created_at = models.DateTimeField('创建时间', auto_now_add=True)
class Meta:
verbose_name = '设备分类'
verbose_name_plural = verbose_name
ordering = ['name']
def __str__(self):
return self.name
class Asset(models.Model):
"""硬件资产"""
# 基本信息
asset_number = models.CharField('资产编号', max_length=50, db_index=True)
name = models.CharField('设备名称', max_length=100)
category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name='设备分类', related_name='assets')
# 硬件信息
brand = models.CharField('品牌', max_length=200, blank=True, default='')
model = models.CharField('型号', max_length=200, blank=True, default='')
asset_value = models.CharField('资产面值', max_length=50, blank=True, default='')
serial_number = models.CharField('序列号', max_length=200, blank=True, default='', db_index=True)
# 位置信息
location = models.CharField('机房', max_length=200, blank=True, default='', help_text='楼层/房间/区域')
cabinet = models.CharField('机柜', max_length=200, blank=True, default='')
cabinet_position = models.CharField('机柜位置', max_length=200, blank=True, default='', help_text='U位')
# 网络信息
bmc_address = models.CharField('BMC地址', max_length=200, blank=True, default='')
ip_address = models.CharField('IP地址', max_length=200, blank=True, default='')
# 显卡信息
has_gpu = models.CharField('是否带卡', max_length=50, blank=True, default='')
gpu_type = models.CharField('显卡类型', max_length=200, blank=True, default='')
gpu_count = models.CharField('卡数', max_length=50, blank=True, default='')
# 采购与质保
purchase_date = models.CharField('采购日期', max_length=50, blank=True, default='')
warranty_expire = models.CharField('质保到期', max_length=50, blank=True, default='')
supplier = models.CharField('供应商', max_length=200, blank=True, default='')
# 管理信息
responsible_person = models.CharField('负责人', max_length=200, blank=True, default='')
department = models.CharField('使用部门', max_length=200, blank=True, default='')
user = models.CharField('维护人', max_length=200, blank=True, default='')
business_type = models.CharField('业务类型', max_length=200, blank=True, default='')
STATUS_CHOICES = [
('in_use', '在用'),
('idle', '闲置'),
('maintenance', '维修中'),
('scrapped', '已报废'),
]
status = models.CharField('状态', max_length=50, choices=STATUS_CHOICES, default='in_use')
remark = models.CharField('备注', max_length=500, blank=True, default='')
# 系统字段
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='创建人')
created_at = models.DateTimeField('创建时间', auto_now_add=True)
updated_at = models.DateTimeField('更新时间', auto_now=True)
class Meta:
verbose_name = '硬件资产'
verbose_name_plural = verbose_name
ordering = ['id']
def __str__(self):
return f'{self.asset_number} - {self.name}'
@property
def is_expired(self):
if self.warranty_expire:
try:
from datetime import datetime
expire_date = datetime.strptime(self.warranty_expire, '%Y-%m-%d').date()
return expire_date < date.today()
except (ValueError, TypeError):
return False
return False
@property
def is_expiring_soon(self):
if self.warranty_expire:
try:
from datetime import datetime, timedelta
expire_date = datetime.strptime(self.warranty_expire, '%Y-%m-%d').date()
return date.today() <= expire_date <= date.today() + timedelta(days=30)
except (ValueError, TypeError):
return False
return False
class AssetChangeLog(models.Model):
"""资产变更记录"""
ACTION_CHOICES = [
('create', '创建'),
('update', '更新'),
('delete', '删除'),
('import', '导入'),
('export', '导出'),
('status_change', '状态变更'),
]
asset = models.ForeignKey(Asset, on_delete=models.SET_NULL, null=True, blank=True,
verbose_name='资产', related_name='change_logs')
asset_number = models.CharField('资产编号', max_length=50, db_index=True)
action = models.CharField('操作类型', max_length=20, choices=ACTION_CHOICES)
field_name = models.CharField('变更字段', max_length=50, blank=True, default='')
old_value = models.TextField('旧值', blank=True, default='')
new_value = models.TextField('新值', blank=True, default='')
description = models.TextField('描述', blank=True, default='')
operator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='操作人')
created_at = models.DateTimeField('操作时间', auto_now_add=True)
class Meta:
verbose_name = '变更记录'
verbose_name_plural = verbose_name
ordering = ['-created_at']
def __str__(self):
return f'{self.asset_number} - {self.get_action_display()}'