From 014b861ae2e5a6eebdfb4433ab4e27af7275c973 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 6 Sep 2023 11:19:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A0=A1=E5=87=86=E6=A3=80=E5=AE=9A?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E8=A1=A8=E5=8F=8A=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/em/migrations/0004_auto_20230906_1111.py | 50 +++++++++++++++++++ apps/em/models.py | 22 +++++--- apps/em/serializers.py | 18 ++++++- apps/em/urls.py | 3 +- apps/em/views.py | 39 +++++++++++++-- 5 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 apps/em/migrations/0004_auto_20230906_1111.py diff --git a/apps/em/migrations/0004_auto_20230906_1111.py b/apps/em/migrations/0004_auto_20230906_1111.py new file mode 100644 index 00000000..c09ab2b0 --- /dev/null +++ b/apps/em/migrations/0004_auto_20230906_1111.py @@ -0,0 +1,50 @@ +# Generated by Django 3.2.12 on 2023-09-06 03:11 + +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), + ('em', '0003_equipment_use_date'), + ] + + operations = [ + migrations.AddField( + model_name='equipment', + name='management_level', + field=models.CharField(default='A', max_length=10, verbose_name='管理等级'), + ), + migrations.AddField( + model_name='equipment', + name='measurement_range', + field=models.CharField(blank=True, default='', max_length=100, verbose_name='量程范围'), + ), + migrations.AddField( + model_name='equipment', + name='meter_type', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='仪表类型'), + ), + migrations.CreateModel( + name='EcheckRecord', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, 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='删除标记')), + ('check_date', models.DateField(verbose_name='校准/鉴定日期')), + ('note', models.TextField(blank=True, null=True, verbose_name='备注')), + ('result', models.PositiveSmallIntegerField(choices=[(10, '正常'), (20, '异常')], default=10, help_text="((10, '正常'), (20, '异常'))", verbose_name='结果')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('equipment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='关联设备')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/em/models.py b/apps/em/models.py index 1f326c77..5bc4d4c3 100644 --- a/apps/em/models.py +++ b/apps/em/models.py @@ -60,6 +60,9 @@ class Equipment(CommonBModel): # usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1) # way = models.IntegerField('校准或检定方式', choices=way_choices, default=1) # standard = models.CharField('溯源标准或依据', max_length=200, default='', blank=True) + meter_type = models.CharField('仪表类型', max_length=100, null=True, blank=True) + management_level = models.CharField('管理等级', max_length=10, default='A') + measurement_range = models.CharField('量程范围', max_length=100, default='', blank=True) use_date = models.DateField('启用日期', null=True, blank=True) cycle = models.PositiveSmallIntegerField('校准或检定周期(月)', null=True, blank=True) check_date = models.DateField('最近校准检查日期', blank=True, null=True) @@ -74,10 +77,15 @@ class Equipment(CommonBModel): return self.number + '-' + self.name -# class EcheckRecord(CommonADModel): -# """ -# 校准鉴定记录 -# """ -# equipment = models.ForeignKey(Equipment, verbose_name='关联设备', on_delete=models.CASCADE) -# check_date = models.DateField('校准检查日期') -# result = models.CharField('结果', max_length=200, blank=True, null=True) \ No newline at end of file +class EcheckRecord(CommonADModel): + """ + 校准检定记录 + """ + CHECK_CHOICES = ( + (10, '正常'), + (20, '异常') + ) + equipment = models.ForeignKey(Equipment, verbose_name='关联设备', on_delete=models.CASCADE) + check_date = models.DateField('校准/鉴定日期') + note = models.TextField('备注', null=True, blank=True) + result = models.PositiveSmallIntegerField('结果', default=10, choices=CHECK_CHOICES, help_text=str(CHECK_CHOICES)) \ No newline at end of file diff --git a/apps/em/serializers.py b/apps/em/serializers.py index 4021f494..8e2bd800 100644 --- a/apps/em/serializers.py +++ b/apps/em/serializers.py @@ -1,8 +1,9 @@ from apps.utils.serializers import CustomModelSerializer -from apps.em.models import Equipment +from apps.em.models import Equipment, EcheckRecord from apps.system.models import Dept from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from rest_framework import serializers +from rest_framework.exceptions import ValidationError class EquipmentSerializer(CustomModelSerializer): belong_dept = serializers.PrimaryKeyRelatedField(label='责任部门', queryset = Dept.objects.all()) @@ -11,4 +12,17 @@ class EquipmentSerializer(CustomModelSerializer): class Meta: model = Equipment fields = '__all__' - read_only_fields = EXCLUDE_FIELDS + ['check_date', 'next_check_date', 'keeper_name', 'belong_dept_name'] \ No newline at end of file + read_only_fields = EXCLUDE_FIELDS + ['check_date', 'next_check_date', 'keeper_name', 'belong_dept_name'] + + +class EcheckRecordSerializer(CustomModelSerializer): + class Meta: + model = EcheckRecord + fields = '__all__' + + def validate(self, attrs): + attrs = super().validate(attrs) + check_date = attrs['check_date'] + if EcheckRecord.objects.filter(check_date__gte=check_date, equipment=attrs['equipment']).exists(): + raise ValidationError('检定日期小于历史记录') + diff --git a/apps/em/urls.py b/apps/em/urls.py index e35b47cb..98c954ed 100644 --- a/apps/em/urls.py +++ b/apps/em/urls.py @@ -1,12 +1,13 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.em.views import EquipmentViewSet +from apps.em.views import EquipmentViewSet, EcheckRecordViewSet API_BASE_URL = 'api/em/' HTML_BASE_URL = 'em/' router = DefaultRouter() router.register('equipment', EquipmentViewSet, basename='equipment') +router.register('echeckrecord', EcheckRecordViewSet, basename='echeckrecord') urlpatterns = [ path(API_BASE_URL, include(router.urls)), ] \ No newline at end of file diff --git a/apps/em/views.py b/apps/em/views.py index 4fb25553..a9a10a26 100644 --- a/apps/em/views.py +++ b/apps/em/views.py @@ -1,9 +1,11 @@ from django.shortcuts import render -from apps.em.models import Equipment -from apps.utils.viewsets import CustomModelViewSet -from apps.em.serializers import EquipmentSerializer +from apps.em.models import Equipment, EcheckRecord +from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet +from apps.em.serializers import EquipmentSerializer, EcheckRecordSerializer from apps.em.filters import EquipFilterSet from rest_framework.exceptions import ParseError +from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin +from dateutil.relativedelta import relativedelta # Create your views here. class EquipmentViewSet(CustomModelViewSet): @@ -16,4 +18,33 @@ class EquipmentViewSet(CustomModelViewSet): def filter_queryset(self, queryset): if not self.detail and not self.request.query_params.get('type', None): raise ParseError('请指定设备类型') - return super().filter_queryset(queryset) \ No newline at end of file + return super().filter_queryset(queryset) + + +class EcheckRecordViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, CustomGenericViewSet): + perms_map = {'get': '*', 'post': 'echeckreocrd.create', 'put': 'echeckrecord.update', 'delete': 'echeckreocrd.delete'} + queryset = EcheckRecord.objects.all() + serializer_class = EcheckRecordSerializer + select_related_fields = ['equipment', 'create_by'] + filterset_fields = ['equipment', 'result'] + + def perform_create(self, serializer): + instance = serializer.save() + equipment = instance.equipment + if equipment.cycle: + equipment.check_date = instance.check_date + equipment.next_check_date = instance.check_date + relativedelta(months=equipment.cycle) + equipment.save() + + def perform_destroy(self, instance): + instance.delete() + equipment = instance.equipment + er = EcheckRecord.objects.filter(equipment=equipment).order_by('check_date').last() + if er: + equipment.check_date = instance.check_date + equipment.next_check_date = instance.check_date + relativedelta(months=equipment.cycle) + equipment.save() + else: + equipment.check_date = None + equipment.next_check_date = None + equipment.save() \ No newline at end of file