初始提交:希姆计算硬件资产管理系统
功能: - Django + MySQL + 深色主题 - 资产增删改查(含资产编号、BMC地址、设备位置、备注) - Excel导入导出(分类自动创建) - 设备分类管理 - 资产变更记录追踪 - 质保到期提醒 - 用户认证系统 - Docker部署支持
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
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):
|
||||
"""硬件资产"""
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('in_use', '在用'),
|
||||
('idle', '闲置'),
|
||||
('maintenance', '维修中'),
|
||||
('scrapped', '已报废'),
|
||||
]
|
||||
|
||||
# 基本信息
|
||||
asset_number = models.CharField('资产编号', max_length=50, unique=True, 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=50, blank=True, default='')
|
||||
model = models.CharField('型号', max_length=100, blank=True, default='')
|
||||
serial_number = models.CharField('序列号', max_length=100, blank=True, default='', db_index=True)
|
||||
|
||||
# 位置信息
|
||||
location = models.CharField('设备位置', max_length=200, blank=True, default='', help_text='楼层/房间/区域')
|
||||
cabinet = models.CharField('机柜', max_length=50, blank=True, default='')
|
||||
cabinet_position = models.CharField('机柜位置', max_length=50, blank=True, default='', help_text='U位')
|
||||
|
||||
# 网络信息
|
||||
bmc_address = models.GenericIPAddressField('BMC地址', blank=True, null=True)
|
||||
ip_address = models.GenericIPAddressField('IP地址', blank=True, null=True)
|
||||
|
||||
# 采购与质保
|
||||
purchase_date = models.DateField('采购日期', blank=True, null=True)
|
||||
warranty_expire = models.DateField('质保到期', blank=True, null=True)
|
||||
supplier = models.CharField('供应商', max_length=100, blank=True, default='')
|
||||
|
||||
# 管理信息
|
||||
responsible_person = models.CharField('负责人', max_length=50, blank=True, default='')
|
||||
status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='in_use')
|
||||
remark = models.TextField('备注', 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 = ['-created_at']
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.asset_number} - {self.name}'
|
||||
|
||||
@property
|
||||
def is_expired(self):
|
||||
if self.warranty_expire:
|
||||
return self.warranty_expire < date.today()
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_expiring_soon(self):
|
||||
if self.warranty_expire:
|
||||
from datetime import timedelta
|
||||
return date.today() <= self.warranty_expire <= date.today() + timedelta(days=30)
|
||||
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()}'
|
||||
Reference in New Issue
Block a user