v1.0.0: 希姆计算资产管理系统正式版
This commit is contained in:
+17
-8
@@ -13,6 +13,7 @@ EXPORT_COLUMNS = [
|
||||
('category', '设备分类', 12),
|
||||
('brand', '品牌', 12),
|
||||
('model', '型号', 20),
|
||||
('asset_value', '资产面值', 12),
|
||||
('serial_number', '序列号', 25),
|
||||
('location', '设备位置', 20),
|
||||
('cabinet', '机柜', 10),
|
||||
@@ -23,6 +24,8 @@ EXPORT_COLUMNS = [
|
||||
('warranty_expire', '质保到期', 12),
|
||||
('supplier', '供应商', 15),
|
||||
('responsible_person', '负责人', 10),
|
||||
('department', '使用部门', 15),
|
||||
('user', '使用人', 10),
|
||||
('status', '状态', 8),
|
||||
('remark', '备注', 30),
|
||||
]
|
||||
@@ -100,8 +103,8 @@ def generate_import_template():
|
||||
# 示例数据行
|
||||
example_data = [
|
||||
'IT-2024-0001', '测试服务器', '服务器', 'Dell', 'PowerEdge R740',
|
||||
'ABC123456', '3楼机房A区', 'A01', 'U10-U15', '192.168.1.200',
|
||||
'192.168.1.100', '2024-01-15', '2027-01-15', '戴尔科技', '张三', '在用', '测试备注'
|
||||
'50000.00', 'ABC123456', '3楼机房A区', 'A01', 'U10-U15', '192.168.1.200',
|
||||
'192.168.1.100', '2024-01-15', '2027-01-15', '戴尔科技', '张三', '研发部', '李四', '在用', '测试备注'
|
||||
]
|
||||
for col_idx, value in enumerate(example_data, 1):
|
||||
cell = ws.cell(row=2, column=col_idx, value=value)
|
||||
@@ -147,12 +150,6 @@ def import_assets_from_excel(ws, category_map, operator=None):
|
||||
results['errors'].append(f'第{row_idx}行: 缺少资产编号')
|
||||
continue
|
||||
|
||||
# 检查重复
|
||||
if Asset.objects.filter(asset_number=asset_number).exists():
|
||||
results['skipped'] += 1
|
||||
results['errors'].append(f'第{row_idx}行: 资产编号 {asset_number} 已存在')
|
||||
continue
|
||||
|
||||
# 处理分类 - 不存在则自动创建
|
||||
category_name = data.get('category', '').strip()
|
||||
category = category_map.get(category_name)
|
||||
@@ -187,12 +184,22 @@ def import_assets_from_excel(ws, category_map, operator=None):
|
||||
bmc_address = data.get('bmc_address') or None
|
||||
ip_address = data.get('ip_address') or None
|
||||
|
||||
# 处理资产面值
|
||||
from decimal import Decimal, InvalidOperation
|
||||
asset_value = None
|
||||
if data.get('asset_value'):
|
||||
try:
|
||||
asset_value = Decimal(str(data['asset_value']).replace(',', ''))
|
||||
except (InvalidOperation, ValueError):
|
||||
pass
|
||||
|
||||
asset = Asset.objects.create(
|
||||
asset_number=asset_number,
|
||||
name=data.get('name', ''),
|
||||
category=category,
|
||||
brand=data.get('brand', ''),
|
||||
model=data.get('model', ''),
|
||||
asset_value=asset_value,
|
||||
serial_number=data.get('serial_number', ''),
|
||||
location=data.get('location', ''),
|
||||
cabinet=data.get('cabinet', ''),
|
||||
@@ -203,6 +210,8 @@ def import_assets_from_excel(ws, category_map, operator=None):
|
||||
warranty_expire=warranty_expire,
|
||||
supplier=data.get('supplier', ''),
|
||||
responsible_person=data.get('responsible_person', ''),
|
||||
department=data.get('department', ''),
|
||||
user=data.get('user', ''),
|
||||
status=status,
|
||||
remark=data.get('remark', ''),
|
||||
created_by=operator,
|
||||
|
||||
+2
-2
@@ -6,10 +6,10 @@ class AssetForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Asset
|
||||
fields = [
|
||||
'asset_number', 'name', 'category', 'brand', 'model', 'serial_number',
|
||||
'asset_number', 'name', 'category', 'brand', 'model', 'asset_value', 'serial_number',
|
||||
'location', 'cabinet', 'cabinet_position', 'bmc_address', 'ip_address',
|
||||
'purchase_date', 'warranty_expire', 'supplier',
|
||||
'responsible_person', 'status', 'remark',
|
||||
'responsible_person', 'department', 'user', 'status', 'remark',
|
||||
]
|
||||
widgets = {
|
||||
'purchase_date': forms.DateInput(attrs={'type': 'date'}),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-25 00:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assetapp', '0002_asset_bmc_address'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_number',
|
||||
field=models.CharField(db_index=True, max_length=50, verbose_name='资产编号'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-25 00:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assetapp', '0003_alter_asset_asset_number'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='department',
|
||||
field=models.CharField(blank=True, default='', max_length=100, verbose_name='使用部门'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='user',
|
||||
field=models.CharField(blank=True, default='', max_length=50, verbose_name='使用人'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-25 00:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assetapp', '0004_asset_department_asset_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='asset_value',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True, verbose_name='资产面值'),
|
||||
),
|
||||
]
|
||||
+4
-1
@@ -29,13 +29,14 @@ class Asset(models.Model):
|
||||
]
|
||||
|
||||
# 基本信息
|
||||
asset_number = models.CharField('资产编号', max_length=50, unique=True, db_index=True)
|
||||
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=50, blank=True, default='')
|
||||
model = models.CharField('型号', max_length=100, blank=True, default='')
|
||||
asset_value = models.DecimalField('资产面值', max_digits=12, decimal_places=2, blank=True, null=True)
|
||||
serial_number = models.CharField('序列号', max_length=100, blank=True, default='', db_index=True)
|
||||
|
||||
# 位置信息
|
||||
@@ -54,6 +55,8 @@ class Asset(models.Model):
|
||||
|
||||
# 管理信息
|
||||
responsible_person = models.CharField('负责人', max_length=50, blank=True, default='')
|
||||
department = models.CharField('使用部门', max_length=100, blank=True, default='')
|
||||
user = 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='')
|
||||
|
||||
|
||||
+5
-3
@@ -99,7 +99,9 @@ def asset_list(request):
|
||||
Q(brand__icontains=search) |
|
||||
Q(model__icontains=search) |
|
||||
Q(location__icontains=search) |
|
||||
Q(responsible_person__icontains=search)
|
||||
Q(responsible_person__icontains=search) |
|
||||
Q(department__icontains=search) |
|
||||
Q(user__icontains=search)
|
||||
)
|
||||
|
||||
# 筛选
|
||||
@@ -116,8 +118,8 @@ def asset_list(request):
|
||||
queryset = queryset.filter(location__icontains=location)
|
||||
|
||||
# 排序
|
||||
sort = request.GET.get('sort', '-created_at')
|
||||
valid_sorts = ['asset_number', '-asset_number', 'name', '-name',
|
||||
sort = request.GET.get('sort', 'id')
|
||||
valid_sorts = ['id', '-id', 'asset_number', '-asset_number', 'name', '-name',
|
||||
'created_at', '-created_at', 'updated_at', '-updated_at',
|
||||
'purchase_date', '-purchase_date']
|
||||
if sort not in valid_sorts:
|
||||
|
||||
Reference in New Issue
Block a user