Merge branch 'master' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory
This commit is contained in:
commit
d8ad57fa7e
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.12 on 2025-09-19 01:08
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wf', '0002_alter_state_filter_dept'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='workflow',
|
||||
name='view_path',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='前端自定义页面路径'),
|
||||
),
|
||||
]
|
|
@ -21,6 +21,7 @@ class Workflow(CommonAModel):
|
|||
'标题模板', max_length=50, default='{title}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:你有一个待办工单:{title}')
|
||||
content_template = models.CharField(
|
||||
'内容模板', max_length=1000, default='标题:{title}, 创建时间:{create_time}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:标题:{title}, 创建时间:{create_time}')
|
||||
view_path = models.TextField('前端自定义页面路径', null=True, blank=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工作流'
|
||||
|
|
|
@ -27,7 +27,7 @@ class StateSerializer(CustomModelSerializer):
|
|||
class WorkflowSimpleSerializer(CustomModelSerializer):
|
||||
class Meta:
|
||||
model = Workflow
|
||||
fields = ['id', 'name', 'key']
|
||||
fields = ['id', 'name', 'key', 'view_path']
|
||||
|
||||
|
||||
class StateSimpleSerializer(CustomModelSerializer):
|
||||
|
|
|
@ -1149,6 +1149,12 @@ class HandoverbSerializer(CustomModelSerializer):
|
|||
read_only_fields = EXCLUDE_FIELDS_BASE + ['handover']
|
||||
extra_kwargs = {'wm': {'required': True}}
|
||||
|
||||
class HandoverbListSerializer(CustomModelSerializer):
|
||||
defect_name = serializers.CharField(source="wm.defect.name", read_only=True)
|
||||
class Meta:
|
||||
model = Handoverb
|
||||
fields = "__all__"
|
||||
|
||||
class HandoverSerializer(CustomModelSerializer):
|
||||
# wm = serializers.PrimaryKeyRelatedField(
|
||||
# label='车间库存ID', queryset=WMaterial.objects.all())
|
||||
|
@ -1363,6 +1369,8 @@ class HandoverUpdateSerializer(CustomModelSerializer):
|
|||
model = Handover
|
||||
fields = ['id', 'send_date', 'send_user', 'count', 'count_eweight', 'recive_user', 'note']
|
||||
|
||||
class HandoverListSerializer(HandoverSerializer):
|
||||
handoverb = HandoverbListSerializer(many=True, required=False)
|
||||
|
||||
|
||||
class GenHandoverSerializer(serializers.Serializer):
|
||||
|
|
|
@ -15,7 +15,7 @@ from apps.utils.mixins import CustomListModelMixin, BulkCreateModelMixin, Comple
|
|||
|
||||
from .filters import StLogFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter, MlogbFilter, BatchStFilter, MlogbwFilter
|
||||
from .models import (SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb,
|
||||
Mlogbw, AttLog, OtherLog, Fmlog, BatchSt, MlogbDefect, MlogUser, BatchLog)
|
||||
Mlogbw, AttLog, OtherLog, Fmlog, BatchSt, MlogbDefect, MlogUser, BatchLog, Handoverb)
|
||||
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer,
|
||||
MlogRevertSerializer,
|
||||
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
|
||||
|
@ -25,7 +25,8 @@ from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer,
|
|||
MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer,
|
||||
MlogbOutUpdateSerializer, FmlogSerializer, FmlogUpdateSerializer, BatchStSerializer,
|
||||
MlogbwCreateUpdateSerializer, HandoverMgroupSerializer, MlogListSerializer,
|
||||
MlogbSerializer, MlogUserSerializer, BatchLogSerializer, MlogQuickSerializer, MlogbwStartTestSerializer)
|
||||
MlogbSerializer, MlogUserSerializer, BatchLogSerializer, MlogQuickSerializer,
|
||||
MlogbwStartTestSerializer, HandoverListSerializer)
|
||||
from .services import mlog_submit, handover_submit, mlog_revert, get_batch_dag, handover_revert
|
||||
from apps.wpm.services import mlog_submit_validate, generate_new_batch
|
||||
from apps.wf.models import State, Ticket
|
||||
|
@ -493,12 +494,15 @@ class HandoverViewSet(CustomModelViewSet):
|
|||
交接记录
|
||||
"""
|
||||
queryset = Handover.objects.all()
|
||||
list_serializer_class = HandoverListSerializer
|
||||
serializer_class = HandoverSerializer
|
||||
select_related_fields = ['send_user', 'send_mgroup', 'send_dept', 'recive_user', 'recive_mgroup', 'recive_dept', 'wm']
|
||||
filterset_class = HandoverFilter
|
||||
search_fields = ['id', 'material__name',
|
||||
'material__number', 'material__specification', 'batch', 'material__model', 'b_handover__batch', "new_batch", "wm__batch"]
|
||||
prefetch_related_fields = ["b_handover"]
|
||||
prefetch_related_fields = [
|
||||
Prefetch('b_handover', queryset=Handoverb.objects.select_related('wm__defect'))
|
||||
]
|
||||
|
||||
def perform_destroy(self, instance):
|
||||
user = self.request.user
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
import requests
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
import threading
|
||||
|
||||
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
BASE_DIR = os.path.dirname(CUR_DIR)
|
||||
sys.path.insert(0, BASE_DIR)
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings")
|
||||
django.setup()
|
||||
|
||||
from apps.enm.services import insert_mplogx_item
|
||||
from django.utils import timezone
|
||||
from apps.utils.tasks import send_mail_task
|
||||
from datetime import datetime, timedelta
|
||||
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
BASE_DIR = os.path.dirname(CUR_DIR)
|
||||
sys.path.insert(0, BASE_DIR)
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings")
|
||||
django.setup()
|
||||
|
||||
SERVER = '192.168.1.37'
|
||||
PORT = '8089'
|
||||
PATH = f'http://{SERVER}:{PORT}/GetTagList'
|
||||
|
||||
SERVER2 = '192.168.1.43'
|
||||
PORT2 = '8081'
|
||||
PATH2 = f'http://{SERVER2}:{PORT2}/GetTagList'
|
||||
|
||||
#MIN_LIST = set(range(0,61,5))
|
||||
MIN_LIST = [0]
|
||||
myLogger = logging.getLogger("log")
|
||||
|
||||
|
||||
class MailController:
|
||||
def __init__(self):
|
||||
self.last_sent_time = None
|
||||
self.interval = timedelta(days=1)
|
||||
self.lock = threading.Lock()
|
||||
self._is_sending = False
|
||||
|
||||
def should_send_mail(self):
|
||||
now = datetime.now()
|
||||
# thread_name = threading.current_thread().name
|
||||
with self.lock:
|
||||
if self._is_sending:
|
||||
# myLogger.info(f"线程 {thread_name}: 邮件正在发送中,跳过")
|
||||
return False
|
||||
if self.last_sent_time is None:
|
||||
# myLogger.info(f"线程 {thread_name}: 首次发送邮件")
|
||||
self._is_sending = True
|
||||
return True
|
||||
time_since_last = now - self.last_sent_time
|
||||
if time_since_last > self.interval:
|
||||
# myLogger.info(f"线程 {thread_name}: 距离上次发送已超过间隔,允许发送")
|
||||
self._is_sending = True
|
||||
return True
|
||||
else:
|
||||
# myLogger.info(f"线程 {thread_name}: 距离上次发送不足间隔,跳过")
|
||||
return False
|
||||
|
||||
def mark_as_sent(self):
|
||||
with self.lock:
|
||||
self.last_sent_time = datetime.now()
|
||||
self._is_sending = False
|
||||
myLogger.info("邮件发送状态已重置")
|
||||
|
||||
|
||||
mail_controller = MailController()
|
||||
|
||||
|
||||
def send_error_notification(error_message):
|
||||
"""
|
||||
发送错误通知
|
||||
"""
|
||||
if mail_controller.should_send_mail():
|
||||
try:
|
||||
send_mail_task.delay(subject='insert_kvt_error', message=str(error_message))
|
||||
myLogger.error(f"请求组态王失败:{str(error_message)}")
|
||||
except Exception as e:
|
||||
myLogger.exception(f"发送错误邮件失败: {e}")
|
||||
finally:
|
||||
mail_controller.mark_as_sent()
|
||||
|
||||
def fetch_data(timex, enp_mpoint_dict, path):
|
||||
"""
|
||||
从数据库转存到超表
|
||||
"""
|
||||
response = None
|
||||
try:
|
||||
response = requests.get(path, timeout=5)
|
||||
response.raise_for_status() # 如果响应码不是 200,将触发异常
|
||||
except requests.RequestException as e:
|
||||
send_error_notification(e)
|
||||
|
||||
if response is None:
|
||||
return
|
||||
try:
|
||||
lines = response.text
|
||||
json_line = [line.strip() for line in lines.split('\n') if line.strip() ]
|
||||
current_object = []
|
||||
# 将碎片分组为完整的 JSON 对象
|
||||
for line in json_line:
|
||||
current_object.append(line.strip()) # 将当前行加入对象
|
||||
if line.strip() == '}': # 遇到结束大括号时
|
||||
try:
|
||||
obj_str = ' '.join(current_object).replace(',}', '}')
|
||||
obj_dict = json.loads(obj_str)
|
||||
insert_mplogx_item(obj_dict.get('strVarName'), obj_dict.get('VarValue'), timex, enp_mpoint_dict)
|
||||
except json.JSONDecodeError as e:
|
||||
send_error_notification(e)
|
||||
current_object = [] # 重置,准备处理下一个对象
|
||||
except Exception as e:
|
||||
send_error_notification(e)
|
||||
|
||||
def get_data():
|
||||
last_triggered = None
|
||||
while True:
|
||||
now = timezone.now()
|
||||
now = now.replace(microsecond=0)
|
||||
if now.second in MIN_LIST:
|
||||
if last_triggered != now:
|
||||
last_triggered = now
|
||||
enp_mpoint_dict= {}
|
||||
threads = [
|
||||
threading.Thread(target=fetch_data, args=(now, enp_mpoint_dict, PATH), daemon=True),
|
||||
threading.Thread(target=fetch_data, args=(now, enp_mpoint_dict, PATH2), daemon=True)
|
||||
]
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join(timeout=10) # 设置超时防止线程挂起
|
||||
|
||||
time.sleep(0.5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
get_data()
|
Loading…
Reference in New Issue