270 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
| from apps.utils.serializers import CustomModelSerializer
 | |
| from apps.enm.models import Mpoint, MpointStat, EnStat, EnStat2, MpLogx, Xscript
 | |
| from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
 | |
| from rest_framework import serializers
 | |
| from apps.mtm.models import Mgroup
 | |
| from rest_framework.exceptions import ParseError
 | |
| from django.core.cache import cache
 | |
| from django.db import transaction
 | |
| from django_celery_beat.models import PeriodicTask
 | |
| from django_celery_results.models import TaskResult
 | |
| from apps.system.serializers import PTaskResultSerializer
 | |
| import json
 | |
| from apps.utils.tools import CodeAnalyzer
 | |
| 
 | |
| 
 | |
| class MpointSerializer(CustomModelSerializer):
 | |
|     mgroup = serializers.PrimaryKeyRelatedField(label="测点集", queryset=Mgroup.objects.all(), required=False, allow_null=True)
 | |
|     mgroup_name = serializers.CharField(source="mgroup.name", read_only=True)
 | |
|     belong_dept_name = serializers.CharField(source="belong_dept.name", read_only=True)
 | |
|     ep_monitored_name = serializers.CharField(source="ep_monitored.name", read_only=True)
 | |
|     ep_monitored_power_kw = serializers.CharField(source="ep_monitored.power_kw", read_only=True)
 | |
|     ep_belong_name = serializers.CharField(source="ep_belong.name", read_only=True)
 | |
|     material_name = serializers.CharField(source="material.name", read_only=True)
 | |
|     formula = serializers.CharField(allow_blank=True, required=False)
 | |
|     last_data = serializers.SerializerMethodField()
 | |
|     gather_state = serializers.SerializerMethodField()
 | |
| 
 | |
|     class Meta:
 | |
|         model = Mpoint
 | |
|         fields = "__all__"
 | |
|         read_only_fields = EXCLUDE_FIELDS + ["belong_dept", "cate"]
 | |
| 
 | |
|     def get_last_data(self, obj):
 | |
|         cache_mp = cache.get(Mpoint.cache_key(obj.code))
 | |
|         if isinstance(cache_mp, dict):
 | |
|             last_data = cache_mp.get('last_data', {})
 | |
|         else:
 | |
|             last_data = {}
 | |
|         return last_data
 | |
|     
 | |
|     def get_gather_state(self, obj):
 | |
|         cache_mp = cache.get(Mpoint.cache_key(obj.code))
 | |
|         if isinstance(cache_mp, dict):
 | |
|             gather_state = cache_mp.get('gather_state', -2)
 | |
|         else:
 | |
|             gather_state = -2
 | |
|         return gather_state
 | |
| 
 | |
|     def validate(self, attrs):
 | |
|         if "material" in attrs and attrs["material"]:
 | |
|             attrs["cate"] = "material"
 | |
|         if "mgroup" in attrs and attrs["mgroup"]:
 | |
|             attrs["belong_dept"] = attrs["mgroup"].belong_dept
 | |
|         formula = attrs.get("formula", "")
 | |
|         if formula:
 | |
|             pass
 | |
|         return attrs
 | |
| 
 | |
| 
 | |
| # class MpLogSerializer(CustomModelSerializer):
 | |
| #     mpoint_name = serializers.CharField(source='mpoint.name', read_only=True)
 | |
| #     class Meta:
 | |
| #         model = MpLog
 | |
| #         fields = '__all__'
 | |
| #         read_only_fields = EXCLUDE_FIELDS + ['mpoint_name']
 | |
| 
 | |
| 
 | |
| class MpLogxSerializer(CustomModelSerializer):
 | |
|     """Serializer for EnvData model"""
 | |
| 
 | |
|     class Meta:
 | |
|         model = MpLogx
 | |
|         fields = "__all__"
 | |
| 
 | |
| 
 | |
| class MpointStatSerializer(CustomModelSerializer):
 | |
|     mpoint_name = serializers.CharField(source="mpoint.name", read_only=True)
 | |
|     mpoint_nickname = serializers.CharField(source="mpoint.nickname", read_only=True)
 | |
|     ep_monitored_name = serializers.CharField(source="mpoint.ep_monitored.name", read_only=True)
 | |
|     ep_monitored_number = serializers.CharField(source="mpoint.ep_monitored.number", read_only=True)
 | |
|     ep_monitored_power_kw = serializers.CharField(source="mpoint.ep_monitored.power_kw", read_only=True)
 | |
|     ep_belong_name = serializers.CharField(source="mpoint.ep_belong.name", read_only=True)
 | |
|     mgroup_name = serializers.CharField(source="mgroup.name", read_only=True)
 | |
|     belong_dept_name = serializers.CharField(source="mgroup.belong_dept.name", read_only=True)
 | |
|     sflog_start_time = serializers.DateTimeField(source="sflog.start_time", read_only=True)
 | |
|     sflog_end_time = serializers.DateTimeField(source="sflog.end_time", read_only=True)
 | |
| 
 | |
|     class Meta:
 | |
|         model = MpointStat
 | |
|         fields = "__all__"
 | |
|         read_only_fields = EXCLUDE_FIELDS + ["mpoint_name", "type", "year", "month", "day"]
 | |
| 
 | |
|     def check_required_keys(dictionary, keys):
 | |
|         for key in keys:
 | |
|             if key not in dictionary or not dictionary[key]:
 | |
|                 return False
 | |
|         return True
 | |
|     
 | |
|     def create(self, validated_data):
 | |
|         if MpointStat.objects.filter(mpoint=validated_data["mpoint"], sflog=validated_data["sflog"]).exists():
 | |
|             raise ParseError("该数据已录入")
 | |
|         return super().create(validated_data)
 | |
| 
 | |
|     def validate(self, attrs):
 | |
|         mpoint = attrs["mpoint"]
 | |
|         if 'mgroup' not in attrs:
 | |
|             raise ParseError("请选择工段")
 | |
|         if mpoint.material and mpoint.type is Mpoint.MT_MANUAL and "sflog" in attrs and attrs["sflog"]:
 | |
|             attrs["type"] = "sflog"
 | |
|             sflog = attrs["sflog"]
 | |
|             attrs["year_s"], attrs["month_s"], attrs["day_s"] = sflog.get_ymd
 | |
|             attrs["mgroup"] = sflog.mgroup
 | |
|         else:
 | |
|             raise ParseError("该数据不支持手工录入")
 | |
|         # if 'sflog' in attrs and attrs['sflog']:
 | |
| 
 | |
|         # else:
 | |
|         #     keys = ['hour', 'day_s', 'month_s', 'year_s']
 | |
|         #     for ind, key in enumerate(keys):
 | |
|         #         if key in attrs and attrs['key']:
 | |
|         #             if not self.check_required_keys(attrs, keys[ind+1:]):
 | |
|         #                 raise ParseError('缺少数据')
 | |
|         #             attrs['type'] = key
 | |
|         return super().validate(attrs)
 | |
| 
 | |
|     def to_representation(self, instance):
 | |
|         ret = super().to_representation(instance)
 | |
|         my_dic_keys = list(ret.keys())
 | |
|         for key in my_dic_keys:
 | |
|             ret_one_val = ret[key]
 | |
|             if isinstance(ret_one_val, float):
 | |
|                 ret[key] = "{:.2f}".format(round(ret_one_val, 2))
 | |
|         return ret
 | |
| 
 | |
| 
 | |
| class EnStatSerializer(CustomModelSerializer):
 | |
|     mgroup_name = serializers.CharField(source="mgroup.name", read_only=True)
 | |
|     team_name = serializers.CharField(source="team.name", read_only=True)
 | |
|     belong_dept_name = serializers.CharField(source="mgroup.belong_dept.name", read_only=True)
 | |
| 
 | |
|     class Meta:
 | |
|         model = EnStat
 | |
|         fields = "__all__"
 | |
| 
 | |
|     def to_representation(self, instance):
 | |
|         ret = super().to_representation(instance)
 | |
|         if 'run_sec' in ret:
 | |
|             ret['run_hour'] = ret['run_sec'] / 3600
 | |
|         my_dic_keys = list(ret.keys())
 | |
|         for key in my_dic_keys:
 | |
|             ret_one_val = ret[key]
 | |
|             if isinstance(ret_one_val, float):
 | |
|                 if key in ["en_consume_unit"]:
 | |
|                     ret[key] = "{:.4f}".format(round(ret_one_val, 4))
 | |
|                 else:
 | |
|                     ret[key] = "{:.2f}".format(round(ret_one_val, 2))
 | |
|             qua_data = ret.get("qua_data", {})
 | |
|             equip_elec_data = ret.get("equip_elec_data", {})
 | |
|             if qua_data:
 | |
|                 for item in qua_data:
 | |
|                     if item.get("rate_pass" )is None:
 | |
|                         ret[f'{item["material_name"]}_{item["testitem_name"].replace("-", "")}_rate_pass'] = 0
 | |
|                     else:
 | |
|                         value = item["rate_pass"]
 | |
|                         rounded_value = round(value, 2) if value is not None else 0
 | |
|                         formatted_value = "{:.2f}".format(rounded_value)
 | |
|                         ret[f'{item["material_name"]}_{item["testitem_name"].replace("-", "")}_rate_pass'] = formatted_value
 | |
|             if equip_elec_data:
 | |
|                 for item in equip_elec_data:
 | |
|                     val = item.get("consume_unit", None)
 | |
|                     if val:
 | |
|                         val = "{:.2f}".format(round(val, 2))
 | |
|                     ret[f'{item["equipment_name"]}_consume_unit'] = val
 | |
|         return ret
 | |
| 
 | |
| 
 | |
| class EnStat2Serializer(CustomModelSerializer):
 | |
|     class Meta:
 | |
|         model = EnStat2
 | |
|         fields = "__all__"
 | |
| 
 | |
|     def to_representation(self, instance):
 | |
|         ret = super().to_representation(instance)
 | |
|         my_dic_keys = list(ret.keys())
 | |
|         for key in my_dic_keys:
 | |
|             ret_one_val = ret[key]
 | |
|             if isinstance(ret_one_val, float):
 | |
|                 ret[key] = "{:.2f}".format(round(ret_one_val, 2))
 | |
|         return ret
 | |
| 
 | |
| 
 | |
| class ReCalSerializer(serializers.Serializer):
 | |
|     start_time = serializers.DateTimeField(label="开始时间")
 | |
|     end_time = serializers.DateTimeField(label="结束时间")
 | |
| 
 | |
| 
 | |
| class MpointStatCorrectSerializer(CustomModelSerializer):
 | |
|     class Meta:
 | |
|         model = MpointStat
 | |
|         fields = ['val_correct', 'id']
 | |
| 
 | |
| class EnStatAnaSerializer(serializers.Serializer):
 | |
|     start_date = serializers.DateField(label="开始日期")
 | |
|     end_date = serializers.DateField(label="结束日期")
 | |
| 
 | |
| 
 | |
| class XscriptSerializer(CustomModelSerializer):
 | |
|     myschedule_name = serializers.CharField(source="myschedule.name", read_only=True)
 | |
|     enabled = serializers.BooleanField(source='periodictask.enabled', read_only=True)
 | |
|     last_run_at = serializers.DateTimeField(source='periodictask.last_run_at', read_only=True)
 | |
|     total_run_count = serializers.IntegerField(source='periodictask.total_run_count', read_only=True)
 | |
|     class Meta:
 | |
|         model = Xscript
 | |
|         fields = "__all__"
 | |
|         read_only_fields = EXCLUDE_FIELDS_BASE + ['periodictask', 'change_data']
 | |
|     
 | |
|     def validate(self, attrs):
 | |
|         code = attrs['code']
 | |
|         analyzer = CodeAnalyzer()
 | |
|         analyzer.analyze(code)
 | |
|         if analyzer.errors:
 | |
|             raise ParseError(f'脚本错误:{analyzer.errors[0]}')
 | |
|         return super().validate(attrs)
 | |
| 
 | |
|     @transaction.atomic
 | |
|     def create(self, validated_data):
 | |
|         ins: Xscript = super().create(validated_data)
 | |
|         pobj = PeriodicTask()
 | |
|         pobj.name = f'{ins.name}_{str(ins.id)[-8:]}'
 | |
|         pobj.task = 'apps.enm.tasks.insert_mplogx_from_xscript'
 | |
|         sch = ins.myschedule
 | |
|         if sch.crontab:
 | |
|             pobj.crontab = sch.crontab
 | |
|         elif sch.interval:
 | |
|             pobj.interval = sch.interval
 | |
|         else:
 | |
|             raise ParseError('不支持的定时策略')
 | |
|         pobj.kwargs = json.dumps({'xscript_id': ins.id})
 | |
|         pobj.enabled = False
 | |
|         pobj.save()
 | |
|         ins.periodictask = pobj
 | |
|         ins.save()
 | |
|         return ins
 | |
| 
 | |
|     @transaction.atomic
 | |
|     def update(self, instance, validated_data):
 | |
|         ins = super().update(instance, validated_data)
 | |
|         pobj = instance.periodictask
 | |
|         pobj.name = f'{ins.name}_{str(ins.id)[-8:]}'
 | |
|         sch = ins.myschedule
 | |
|         if sch.crontab:
 | |
|             pobj.crontab = sch.crontab
 | |
|             pobj.interval = None
 | |
|         elif sch.interval:
 | |
|             pobj.interval = sch.interval
 | |
|             pobj.crontab = None
 | |
|         else:
 | |
|             raise ParseError('不支持的定时策略')
 | |
|         pobj.save()
 | |
|         return ins
 | |
|     
 | |
| 
 | |
| class XscriptDetailSerializer(XscriptSerializer):
 | |
|     last_run_data = serializers.SerializerMethodField()
 | |
| 
 | |
|     def get_last_run_data(self, obj):
 | |
|         tr = TaskResult.objects.filter(task_kwargs__contains=obj.id).order_by('-date_done').first()
 | |
|         if tr:
 | |
|             return PTaskResultSerializer(instance=tr).data
 | |
|         return None |