diff --git a/server/apps/consulting/migrations/0009_device.py b/server/apps/consulting/migrations/0009_device.py new file mode 100644 index 0000000..4f40a2b --- /dev/null +++ b/server/apps/consulting/migrations/0009_device.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.12 on 2024-06-26 08:57 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('consulting', '0008_auto_20231204_0931'), + ] + + operations = [ + migrations.CreateModel( + name='Device', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('company_number', models.IntegerField(default=0, verbose_name='公司序号')), + ('company_name', models.CharField(max_length=100, verbose_name='公司名称')), + ('device_name', models.CharField(max_length=100, verbose_name='设备名称')), + ('device_number', models.CharField(blank=True, max_length=100, null=True, verbose_name='设备编号')), + ('spec', models.CharField(blank=True, max_length=100, null=True, verbose_name='规格型号')), + ('manufactor', models.CharField(blank=True, max_length=100, null=True, verbose_name='生产厂家')), + ('dec_parameter', models.CharField(blank=True, max_length=100, null=True, verbose_name='检测参数')), + ('range', models.CharField(blank=True, max_length=100, null=True, verbose_name='测量范围')), + ('precision', models.CharField(blank=True, max_length=100, null=True, verbose_name='精度')), + ('other_parameter', models.TextField(blank=True, null=True, verbose_name='其他技术参数')), + ('department', models.CharField(blank=True, max_length=100, null=True, verbose_name='使用部门')), + ('procurement_time', models.CharField(blank=True, max_length=50, null=True, verbose_name='采购时间')), + ('original_price', models.FloatField(blank=True, default=0, null=True, verbose_name='资产原值')), + ('current_price', models.FloatField(blank=True, default=0, null=True, verbose_name='资产净值')), + ('is_infrastructure', models.BooleanField(default=False, verbose_name='原值是否含基建')), + ('infras_percentage', models.FloatField(default=0, verbose_name='基建原值占比')), + ('is_instructions', models.BooleanField(default=False, verbose_name='是否有说明书')), + ('custodian', models.CharField(blank=True, max_length=20, null=True, verbose_name='保管人')), + ('depositor', models.CharField(blank=True, max_length=20, null=True, verbose_name='存放地点')), + ('contacts', models.CharField(blank=True, max_length=20, null=True, verbose_name='设备联系人')), + ('tel', models.CharField(blank=True, max_length=20, null=True, verbose_name='联系电话')), + ('remark', models.TextField(blank=True, null=True, verbose_name='备注')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='device_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'verbose_name': '设备台账', + 'verbose_name_plural': '设备台账', + }, + ), + ] diff --git a/server/apps/consulting/migrations/0010_alter_device_original_price.py b/server/apps/consulting/migrations/0010_alter_device_original_price.py new file mode 100644 index 0000000..05226e8 --- /dev/null +++ b/server/apps/consulting/migrations/0010_alter_device_original_price.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2024-06-26 08:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0009_device'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='original_price', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='资产原值'), + ), + ] diff --git a/server/apps/consulting/migrations/0011_alter_device_current_price.py b/server/apps/consulting/migrations/0011_alter_device_current_price.py new file mode 100644 index 0000000..b39e628 --- /dev/null +++ b/server/apps/consulting/migrations/0011_alter_device_current_price.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2024-06-26 09:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0010_alter_device_original_price'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='current_price', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='资产净值'), + ), + ] diff --git a/server/apps/consulting/migrations/0012_alter_device_range.py b/server/apps/consulting/migrations/0012_alter_device_range.py new file mode 100644 index 0000000..b9266b2 --- /dev/null +++ b/server/apps/consulting/migrations/0012_alter_device_range.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2024-06-26 09:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0011_alter_device_current_price'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='range', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='量程'), + ), + ] diff --git a/server/apps/consulting/migrations/0013_auto_20240626_1718.py b/server/apps/consulting/migrations/0013_auto_20240626_1718.py new file mode 100644 index 0000000..14ecb0b --- /dev/null +++ b/server/apps/consulting/migrations/0013_auto_20240626_1718.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.12 on 2024-06-26 09:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0012_alter_device_range'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='dec_parameter', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='检测参数'), + ), + migrations.AlterField( + model_name='device', + name='device_number', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='设备编号'), + ), + migrations.AlterField( + model_name='device', + name='manufactor', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='生产厂家'), + ), + migrations.AlterField( + model_name='device', + name='precision', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='精度'), + ), + migrations.AlterField( + model_name='device', + name='spec', + field=models.CharField(blank=True, max_length=200, null=True, verbose_name='规格型号'), + ), + ] diff --git a/server/apps/consulting/migrations/0014_auto_20240626_1718.py b/server/apps/consulting/migrations/0014_auto_20240626_1718.py new file mode 100644 index 0000000..35a6613 --- /dev/null +++ b/server/apps/consulting/migrations/0014_auto_20240626_1718.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.12 on 2024-06-26 09:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0013_auto_20240626_1718'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='dec_parameter', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='检测参数'), + ), + migrations.AlterField( + model_name='device', + name='device_number', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='设备编号'), + ), + migrations.AlterField( + model_name='device', + name='manufactor', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='生产厂家'), + ), + migrations.AlterField( + model_name='device', + name='spec', + field=models.CharField(blank=True, max_length=500, null=True, verbose_name='规格型号'), + ), + ] diff --git a/server/apps/consulting/migrations/0015_alter_device_id.py b/server/apps/consulting/migrations/0015_alter_device_id.py new file mode 100644 index 0000000..bc218bd --- /dev/null +++ b/server/apps/consulting/migrations/0015_alter_device_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.12 on 2024-06-27 01:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('consulting', '0014_auto_20240626_1718'), + ] + + operations = [ + migrations.AlterField( + model_name='device', + name='id', + field=models.AutoField(primary_key=True, serialize=False), + ), + ] diff --git a/server/apps/consulting/models.py b/server/apps/consulting/models.py index 43e4fe7..3a2b60a 100644 --- a/server/apps/consulting/models.py +++ b/server/apps/consulting/models.py @@ -1,6 +1,7 @@ from django.db import models from utils.model import BaseModel -from apps.system.models import CommonAModel, File +from apps.system.models import CommonAModel, File, CommonADModel +from django.utils import timezone # Create your models here. @@ -69,4 +70,33 @@ class Validation(CommonAModel): choices=filetype_choices, default=1) class Meta: verbose_name = '能力验证' - verbose_name_plural = verbose_name \ No newline at end of file + verbose_name_plural = verbose_name + +class Device(CommonADModel): + id = models.AutoField(primary_key=True) + company_number = models.IntegerField('公司序号', default=0) + company_name = models.CharField('公司名称', max_length=100) + device_name = models.CharField('设备名称', max_length=100) + device_number = models.CharField('设备编号', max_length=500, null=True, blank=True) + spec = models.CharField('规格型号', max_length=500, null=True, blank=True) + manufactor = models.CharField('生产厂家', max_length=500, null=True, blank=True) + dec_parameter = models.CharField('检测参数', max_length=500, null=True, blank=True) + range = models.CharField('量程', max_length=500, null=True, blank=True) + precision = models.CharField('精度', max_length=500, null=True, blank=True) + other_parameter = models.TextField('其他技术参数', null=True, blank=True) + department = models.CharField('使用部门', max_length=100, null=True, blank=True) + procurement_time = models.CharField('采购时间', max_length=50, null=True, blank=True) + original_price = models.CharField('资产原值', max_length=50, null=True, blank=True) + current_price = models.CharField('资产净值', max_length=50, null=True, blank=True) + is_infrastructure = models.BooleanField('原值是否含基建', default=False) + infras_percentage = models.FloatField('基建原值占比', default=0) + is_instructions = models.BooleanField('是否有说明书', default=False) + custodian = models.CharField('保管人', max_length=20, null=True, blank=True) + depositor = models.CharField('存放地点', max_length=20, null=True, blank=True) + contacts = models.CharField('设备联系人', max_length=20, null=True, blank=True) + tel = models.CharField('联系电话', max_length=20, null=True, blank=True) + remark = models.TextField('备注', null=True, blank=True) + + class Meta: + verbose_name = '设备台账' + verbose_name_plural = verbose_name diff --git a/server/apps/consulting/serializers.py b/server/apps/consulting/serializers.py index f8a589e..3942d94 100644 --- a/server/apps/consulting/serializers.py +++ b/server/apps/consulting/serializers.py @@ -2,6 +2,7 @@ from re import template from django.db.models.base import Model from rest_framework import serializers from .models import * +# from apps.consulting.models import Device from apps.system.serializers import FileSerializer from rest_framework.exceptions import ParseError, APIException @@ -44,4 +45,12 @@ class ValidationSerializer(serializers.ModelSerializer): @staticmethod def setup_eager_loading(queryset): queryset = queryset.select_related('file') - return queryset \ No newline at end of file + return queryset + + +class DeviceSerializer(serializers.ModelSerializer): + + class Meta: + model = Device + fields = '__all__' + diff --git a/server/apps/consulting/urls.py b/server/apps/consulting/urls.py index fc59a21..33a5f27 100644 --- a/server/apps/consulting/urls.py +++ b/server/apps/consulting/urls.py @@ -1,12 +1,13 @@ from django.urls import path, include from rest_framework import routers -from .views import RegulatoryViewSet,ProfessionalViewSet,PolicyViewSet,ValidationViewSet +from .views import RegulatoryViewSet,ProfessionalViewSet,DeviceViewSet,PolicyViewSet,ValidationViewSet router = routers.DefaultRouter() router.register('regulatory', RegulatoryViewSet, basename='regulatory') router.register('professional', ProfessionalViewSet, basename='professional') router.register('policy', PolicyViewSet, basename='policy') router.register('validation', ValidationViewSet, basename='validation') +router.register('device', DeviceViewSet, basename='device') urlpatterns = [ path('', include(router.urls)) ] diff --git a/server/apps/consulting/views.py b/server/apps/consulting/views.py index 94432e8..f7e1f58 100644 --- a/server/apps/consulting/views.py +++ b/server/apps/consulting/views.py @@ -13,14 +13,16 @@ from rest_framework.permissions import IsAdminUser from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet, ModelViewSet from utils.pagination import PageOrNot - from apps.system.mixins import CreateUpdateCustomMixin, CreateUpdateModelAMixin, OptimizationMixin from apps.system.models import Organization from apps.system.permission import get_permission_list, has_permission from apps.system.permission_data import RbacFilterSet +from rest_framework.serializers import Serializer from .models import * from .serializers import * +from openpyxl import load_workbook + # Create your views here. class RegulatoryViewSet(OptimizationMixin, PageOrNot, CreateUpdateModelAMixin, ModelViewSet): perms_map = {'get': '*', 'post': 'regulatory_create', @@ -77,3 +79,64 @@ class ValidationViewSet(OptimizationMixin, PageOrNot, CreateUpdateModelAMixin, M search_fields = ['provinces'] ordering_fields = ['provinces'] filterset_fields = ['provinces'] + +class DeviceViewSet(ModelViewSet): + perms_map = {'get': '*', 'post': 'device_import'} + queryset = Device.objects.all() + serializer_class = DeviceSerializer + ordering = ['-id'] + search_fields = ['company_name', 'device_name', 'spec', 'manufactor', 'dec_parameter', 'procurement_time'] + + def make_data(self, data, sheet, i): + data["company_number"] = sheet["a" + str(i)].value + data["company_name"] = sheet["b" + str(i)].value + data["device_name"] = sheet["c" + str(i)].value + data["device_number"] = sheet["d" + str(i)].value + data["spec"] = sheet["e" + str(i)].value + data["manufactor"] = sheet["f" + str(i)].value + data["dec_parameter"] = sheet["g" + str(i)].value + data["range"] = sheet["h" + str(i)].value + data["precision"] = sheet["i" + str(i)].value + data["other_parameter"] = sheet["j" + str(i)].value + data["department"] = sheet["k" + str(i)].value + data["procurement_time"] = sheet["l" + str(i)].value + data["original_price"] = sheet["m" + str(i)].value + data["current_price"] = sheet["n" + str(i)].value + data["is_infrastructure"] = True if sheet["o" + str(i)].value=="是" else False + data["infras_percentage"] = sheet["p" + str(i)].value + data["is_instructions"] = True if sheet["q" + str(i)].value=="是" else False + data["custodian"] = sheet["r" + str(i)].value + data["depositor"] = sheet["s" + str(i)].value + data["contacts"] = sheet["t" + str(i)].value + data["tel"] = sheet["u" + str(i)].value + data["remark"] = sheet["v" + str(i)].value + return data + + @action(methods=["post"], detail=False, perms_map={"post": "device_import"}, serializer_class=Serializer) + def imp(self, request, *args, **kwargs): + """导入表格 + + 导入表格 + """ + path = request.data.get("excel_path", "") + full_path = settings.BASE_DIR + path + if not path.endswith(".xlsx"): + raise ParseError("请提供xlsx格式文件") + wb = load_workbook(full_path, data_only=True) + sheet = wb.worksheets[0] + data_list = [] + i = 3 + while sheet["b" + str(i)].value: + data = {} + data = self.make_data(data, sheet, i) + data_list.append(data) + i = i + 1 + instances = [Device(**data) for data in data_list] + Device.objects.all().delete() + Device.objects.bulk_create(instances) + return Response() + + def truncate_table(self, model): + table_name = model._meta.db_table + with connection.cursor() as cursor: + cursor.execute("TRUNCATE TABLE %s;" % table_name)