models.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from django.db import models
  2. from django.contrib.auth.models import User
  3. from datetime import date
  4. class Category(models.Model):
  5. """设备分类"""
  6. name = models.CharField('分类名称', max_length=50, unique=True)
  7. description = models.CharField('描述', max_length=200, blank=True, default='')
  8. created_at = models.DateTimeField('创建时间', auto_now_add=True)
  9. class Meta:
  10. verbose_name = '设备分类'
  11. verbose_name_plural = verbose_name
  12. ordering = ['name']
  13. def __str__(self):
  14. return self.name
  15. class Asset(models.Model):
  16. """硬件资产"""
  17. STATUS_CHOICES = [
  18. ('in_use', '在用'),
  19. ('idle', '闲置'),
  20. ('maintenance', '维修中'),
  21. ('scrapped', '已报废'),
  22. ]
  23. # 基本信息
  24. asset_number = models.CharField('资产编号', max_length=50, db_index=True)
  25. name = models.CharField('设备名称', max_length=100)
  26. category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name='设备分类', related_name='assets')
  27. # 硬件信息
  28. brand = models.CharField('品牌', max_length=50, blank=True, default='')
  29. model = models.CharField('型号', max_length=100, blank=True, default='')
  30. asset_value = models.DecimalField('资产面值', max_digits=12, decimal_places=2, blank=True, null=True)
  31. serial_number = models.CharField('序列号', max_length=100, blank=True, default='', db_index=True)
  32. # 位置信息
  33. location = models.CharField('机房', max_length=200, blank=True, default='', help_text='楼层/房间/区域')
  34. cabinet = models.CharField('机柜', max_length=50, blank=True, default='')
  35. cabinet_position = models.CharField('机柜位置', max_length=50, blank=True, default='', help_text='U位')
  36. # 网络信息
  37. bmc_address = models.GenericIPAddressField('BMC地址', blank=True, null=True)
  38. ip_address = models.GenericIPAddressField('IP地址', blank=True, null=True)
  39. # 显卡信息
  40. has_gpu = models.CharField('是否带卡', max_length=20, blank=True, default='')
  41. gpu_type = models.CharField('显卡类型', max_length=100, blank=True, default='')
  42. gpu_count = models.IntegerField('卡数', blank=True, null=True)
  43. # 采购与质保
  44. purchase_date = models.DateField('采购日期', blank=True, null=True)
  45. warranty_expire = models.DateField('质保到期', blank=True, null=True)
  46. supplier = models.CharField('供应商', max_length=100, blank=True, default='')
  47. # 管理信息
  48. responsible_person = models.CharField('负责人', max_length=50, blank=True, default='')
  49. department = models.CharField('使用部门', max_length=100, blank=True, default='')
  50. user = models.CharField('维护人', max_length=50, blank=True, default='')
  51. business_type = models.CharField('业务类型', max_length=100, blank=True, default='')
  52. status = models.CharField('状态', max_length=20, choices=STATUS_CHOICES, default='in_use')
  53. remark = models.TextField('备注', blank=True, default='')
  54. # 系统字段
  55. created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='创建人')
  56. created_at = models.DateTimeField('创建时间', auto_now_add=True)
  57. updated_at = models.DateTimeField('更新时间', auto_now=True)
  58. class Meta:
  59. verbose_name = '硬件资产'
  60. verbose_name_plural = verbose_name
  61. ordering = ['id']
  62. def __str__(self):
  63. return f'{self.asset_number} - {self.name}'
  64. @property
  65. def is_expired(self):
  66. if self.warranty_expire:
  67. return self.warranty_expire < date.today()
  68. return False
  69. @property
  70. def is_expiring_soon(self):
  71. if self.warranty_expire:
  72. from datetime import timedelta
  73. return date.today() <= self.warranty_expire <= date.today() + timedelta(days=30)
  74. return False
  75. class AssetChangeLog(models.Model):
  76. """资产变更记录"""
  77. ACTION_CHOICES = [
  78. ('create', '创建'),
  79. ('update', '更新'),
  80. ('delete', '删除'),
  81. ('import', '导入'),
  82. ('export', '导出'),
  83. ('status_change', '状态变更'),
  84. ]
  85. asset = models.ForeignKey(Asset, on_delete=models.SET_NULL, null=True, blank=True,
  86. verbose_name='资产', related_name='change_logs')
  87. asset_number = models.CharField('资产编号', max_length=50, db_index=True)
  88. action = models.CharField('操作类型', max_length=20, choices=ACTION_CHOICES)
  89. field_name = models.CharField('变更字段', max_length=50, blank=True, default='')
  90. old_value = models.TextField('旧值', blank=True, default='')
  91. new_value = models.TextField('新值', blank=True, default='')
  92. description = models.TextField('描述', blank=True, default='')
  93. operator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='操作人')
  94. created_at = models.DateTimeField('操作时间', auto_now_add=True)
  95. class Meta:
  96. verbose_name = '变更记录'
  97. verbose_name_plural = verbose_name
  98. ordering = ['-created_at']
  99. def __str__(self):
  100. return f'{self.asset_number} - {self.get_action_display()}'