fix: 能管的工段异常修改
This commit is contained in:
parent
6f058dc757
commit
2030812c18
|
@ -150,7 +150,8 @@ class CorrectViewSet(CustomGenericViewSet):
|
||||||
from apps.enm.models import Mpoint
|
from apps.enm.models import Mpoint
|
||||||
for mpoint in Mpoint.objects.exclude(mgroup=None):
|
for mpoint in Mpoint.objects.exclude(mgroup=None):
|
||||||
mgroup = mpoint.mgroup
|
mgroup = mpoint.mgroup
|
||||||
mpoint.mgroups_allocate = [{'mgroup': mgroup.id, 'mgroup_name': mgroup.name, 'ratio': 1}]
|
mpoint.mgroups_allocate = [
|
||||||
|
{'mgroup': mgroup.id, 'mgroup_name': mgroup.name, 'ratio': 1}]
|
||||||
mpoint.save()
|
mpoint.save()
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
@ -209,6 +210,7 @@ class CorrectViewSet(CustomGenericViewSet):
|
||||||
# event.save()
|
# event.save()
|
||||||
# return Response()
|
# return Response()
|
||||||
|
|
||||||
|
|
||||||
class TestViewSet(CustomGenericViewSet):
|
class TestViewSet(CustomGenericViewSet):
|
||||||
authentication_classes = ()
|
authentication_classes = ()
|
||||||
permission_classes = ()
|
permission_classes = ()
|
||||||
|
@ -261,7 +263,8 @@ class TestViewSet(CustomGenericViewSet):
|
||||||
m = importlib.import_module(module)
|
m = importlib.import_module(module)
|
||||||
f = getattr(m, func)
|
f = getattr(m, func)
|
||||||
if vdata['delay']:
|
if vdata['delay']:
|
||||||
task = f.delay(*vdata.get('args', []), **vdata.get('kwargs', {})) # 同步执行
|
task = f.delay(*vdata.get('args', []), **
|
||||||
|
vdata.get('kwargs', {})) # 同步执行
|
||||||
return Response({'task_id': task.id})
|
return Response({'task_id': task.id})
|
||||||
else:
|
else:
|
||||||
f(*vdata.get('args', []), **vdata.get('kwargs', {}))
|
f(*vdata.get('args', []), **vdata.get('kwargs', {}))
|
||||||
|
@ -299,7 +302,8 @@ class TestViewSet(CustomGenericViewSet):
|
||||||
from apps.hrm.services import HrmService
|
from apps.hrm.services import HrmService
|
||||||
# data = {'id': 25198, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1000096$7$0$0', 'deviceCode': '1000096', 'alarmCode': 'd38c98b842334581a8219b3125ca72d5', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg', 'nodeType': '2', 'alarmDate': 1669187805, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '设备管理部', 'deptIdList': [25], 'acsChannelCode': '1000096$7$0$0', 'maskState': 0, 'enterOrExit': 1, 'openTypeStr': '人脸刷门', 'swingTime': '2022-11-23 15:16:45', 'deviceName': '厂区门入', 'personCode': '8jtfoa', 'openType': '61', 'isOverTemp': False, 'orgCode': '001', 'paperNumber': '61012419850304335X', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1044994923113353216, 'beginTime': 1669187805000, 'acsChannelName': '厂区门入_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': ['http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '25', 'cardType': 0, 'curTemp': 35.5, 'deviceCode': '1000096', 'personName': '谭刚位', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20221110/1/3313679c-6092-11ed-b963-e4246c7d1635.jpg', 'openResult': 1, 'personId': 673, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg', 'category': '0', 'cardNumber': '0525871590', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '厂区门入_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
# data = {'id': 25198, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1000096$7$0$0', 'deviceCode': '1000096', 'alarmCode': 'd38c98b842334581a8219b3125ca72d5', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg', 'nodeType': '2', 'alarmDate': 1669187805, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '设备管理部', 'deptIdList': [25], 'acsChannelCode': '1000096$7$0$0', 'maskState': 0, 'enterOrExit': 1, 'openTypeStr': '人脸刷门', 'swingTime': '2022-11-23 15:16:45', 'deviceName': '厂区门入', 'personCode': '8jtfoa', 'openType': '61', 'isOverTemp': False, 'orgCode': '001', 'paperNumber': '61012419850304335X', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1044994923113353216, 'beginTime': 1669187805000, 'acsChannelName': '厂区门入_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': ['http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '25', 'cardType': 0, 'curTemp': 35.5, 'deviceCode': '1000096', 'personName': '谭刚位', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20221110/1/3313679c-6092-11ed-b963-e4246c7d1635.jpg', 'openResult': 1, 'personId': 673, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221123/1/dsf_43aee9e6-6ae2-11ed-9872-e4246c7d1635_42018473_42037732.jpg', 'category': '0', 'cardNumber': '0525871590', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '厂区门入_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
||||||
# data = {'id': 29870, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1002222$7$0$0', 'deviceCode': '1002222', 'alarmCode': '191f4a8d0a2c4b6282448af04df6ec11', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg', 'nodeType': '2', 'alarmDate': 1669263013, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '安全生产部', 'deptIdList': [28], 'acsChannelCode': '1002222$7$0$0', 'maskState': 3, 'enterOrExit': 3, 'openTypeStr': '人脸刷门', 'swingTime': '2022-11-24 12:10:13', 'deviceName': '办公楼考勤面板', 'personCode': '13911097513', 'openType': '61', 'orgCode': '001', 'paperNumber': '110107196804040335', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1045310360703340544, 'beginTime': 1669263013000, 'acsChannelName': '办公楼考勤面板_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': ['http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '28', 'cardType': 0, 'deviceCode': '1002222', 'personName': '刘静元', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20220907/1/d841d821-2e67-11ed-b073-e4246c7d1635.jpg', 'openResult': 1, 'personId': 237, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg', 'category': '0', 'cardNumber': '5973291203', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '办公楼考勤面板_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
# data = {'id': 29870, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1002222$7$0$0', 'deviceCode': '1002222', 'alarmCode': '191f4a8d0a2c4b6282448af04df6ec11', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg', 'nodeType': '2', 'alarmDate': 1669263013, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '安全生产部', 'deptIdList': [28], 'acsChannelCode': '1002222$7$0$0', 'maskState': 3, 'enterOrExit': 3, 'openTypeStr': '人脸刷门', 'swingTime': '2022-11-24 12:10:13', 'deviceName': '办公楼考勤面板', 'personCode': '13911097513', 'openType': '61', 'orgCode': '001', 'paperNumber': '110107196804040335', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1045310360703340544, 'beginTime': 1669263013000, 'acsChannelName': '办公楼考勤面板_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': ['http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '28', 'cardType': 0, 'deviceCode': '1002222', 'personName': '刘静元', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20220907/1/d841d821-2e67-11ed-b073-e4246c7d1635.jpg', 'openResult': 1, 'personId': 237, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20221124/1/dsf_b8662018-6b9c-11ed-9872-e4246c7d1635_51799202_51816153.jpg', 'category': '0', 'cardNumber': '5973291203', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '办公楼考勤面板_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
||||||
data = {'id': 70781, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1002222$7$0$0', 'deviceCode': '1002222', 'alarmCode': '74ac9b9511774388a975dc5daa6ad8b9', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg', 'nodeType': '2', 'alarmDate': 1681897834, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '企业管理部', 'deptIdList': [21], 'acsChannelCode': '1002222$7$0$0', 'maskState': 0, 'enterOrExit': 3, 'openTypeStr': '人脸刷门', 'swingTime': '2023-04-19 17:50:34', 'deviceName': '办公楼考勤面板', 'personCode': '13731293508', 'openType': '61', 'orgCode': '001', 'paperNumber': '130634198612035821', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1098304215199125504, 'beginTime': 1681897834000, 'acsChannelName': '办公楼考勤面板_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': ['http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '21', 'cardType': 0, 'deviceCode': '1002222', 'personName': '李贝', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20220907/1/9ab9a1eb-2e74-11ed-b073-e4246c7d1635.jpg', 'openResult': 1, 'personId': 331, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg', 'category': '0', 'cardNumber': '6705501569', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '办公楼考勤面板_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
data = {'id': 70781, 'category': 'alarm', 'method': 'alarm.msg', 'info': {'orgName': '河北省', 'nodeCode': '1002222$7$0$0', 'deviceCode': '1002222', 'alarmCode': '74ac9b9511774388a975dc5daa6ad8b9', 'alarmPicture': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg', 'nodeType': '2', 'alarmDate': 1681897834, 'alarmGrade': 2, 'isSave': False, 'unitType': 7, 'extend': {'deptName': '企业管理部', 'deptIdList': [21], 'acsChannelCode': '1002222$7$0$0', 'maskState': 0, 'enterOrExit': 3, 'openTypeStr': '人脸刷门', 'swingTime': '2023-04-19 17:50:34', 'deviceName': '办公楼考勤面板', 'personCode': '13731293508', 'openType': '61', 'orgCode': '001', 'paperNumber': '130634198612035821', 'errorDetail': '', 'from': 'evo-accesscontrol', 'id': 1098304215199125504, 'beginTime': 1681897834000, 'acsChannelName': '办公楼考勤面板_门禁通道_1', 'cardStatus': '0', 'faceImageUrl': [
|
||||||
|
'http://10.99.5.24:8927/6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg'], 'orgName': '河北省', 'openFailedCode': 0, 'sex': 1, 'deptId': '21', 'cardType': 0, 'deviceCode': '1002222', 'personName': '李贝', 'personImg': '6ae577ee-ce45-11ec-bb54-e4246c7d1635/20220907/1/9ab9a1eb-2e74-11ed-b073-e4246c7d1635.jpg', 'openResult': 1, 'personId': 331, 'recordImage1': '6ad010cf-ce45-11ec-9715-e4246c7d1635/20230419/1/dsf_93e4c0ab-de83-11ed-af40-e4246c7d1635_45533104_45552146.jpg', 'category': '0', 'cardNumber': '6705501569', 'rfidType': 0, 'age': 0}, 'alarmType': 61, 'channelSeq': 0, 'orgCode': '001', 'channelName': '办公楼考勤面板_门禁通道_1', 'alarmStat': 1, 'isEvent': True}, 'subsystem': 'evo-accesscontrol', 'userIds': None, 'sid': None, 'domainId': None, 'infoArray': None, 'protocol': None}
|
||||||
HrmService.swipe(data=data)
|
HrmService.swipe(data=data)
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
@ -572,6 +576,6 @@ class TestViewSet(CustomGenericViewSet):
|
||||||
|
|
||||||
@action(methods=['post'], detail=False, serializer_class=Serializer, permission_classes=[])
|
@action(methods=['post'], detail=False, serializer_class=Serializer, permission_classes=[])
|
||||||
def test_cal(self, request, pk=None):
|
def test_cal(self, request, pk=None):
|
||||||
from apps.wpm.tasks import cal_shut_hour
|
from apps.wpm.tasks import cal_exp_duration_hour
|
||||||
cal_shut_hour('3397169058570170368')
|
cal_exp_duration_hour('3397169058570170368')
|
||||||
return Response()
|
return Response()
|
|
@ -14,7 +14,8 @@ def translate_eval_formula(exp_str: str, year: int, month: int, day: int, hour:
|
||||||
pattern = r"\${(.*?)}"
|
pattern = r"\${(.*?)}"
|
||||||
matches = re.findall(pattern, exp_str)
|
matches = re.findall(pattern, exp_str)
|
||||||
for match in matches:
|
for match in matches:
|
||||||
mpst = MpointStat.objects.filter(Q(mpoint__id=match)|Q(mpoint__name=match)|Q(mpoint__code=match), type='hour', year=year, month=month, day=day, hour=hour).first()
|
mpst = MpointStat.objects.filter(Q(mpoint__id=match) | Q(mpoint__name=match) | Q(
|
||||||
|
mpoint__code=match), type='hour', year=year, month=month, day=day, hour=hour).first()
|
||||||
if mpst:
|
if mpst:
|
||||||
exp_str = exp_str.replace(f"${{{match}}}", str(mpst.val))
|
exp_str = exp_str.replace(f"${{{match}}}", str(mpst.val))
|
||||||
rval = eval(exp_str)
|
rval = eval(exp_str)
|
||||||
|
@ -76,27 +77,43 @@ def get_day_s(year: int, month: int, day: int, hour: int, hour_split: int = 21):
|
||||||
# print(traceback.format_exc())
|
# print(traceback.format_exc())
|
||||||
# return goal_data, score
|
# return goal_data, score
|
||||||
|
|
||||||
|
|
||||||
def shutdown_or_startup(mplog: MpLog):
|
def shutdown_or_startup(mplog: MpLog):
|
||||||
from apps.wpm.models import StLog
|
from apps.wpm.models import StLog
|
||||||
from apps.wpm.tasks import cal_shut_hour
|
from apps.wpm.tasks import cal_exp_duration_hour
|
||||||
|
from apps.wpm.services import get_sflog
|
||||||
mpoint = mplog.mpoint
|
mpoint = mplog.mpoint
|
||||||
mgroup = mpoint.mgroup
|
mgroup = mpoint.mgroup
|
||||||
last_stlog = StLog.objects.filter(mgroup=mgroup).order_by('start_time').last()
|
last_stlog = StLog.objects.filter(
|
||||||
|
mgroup=mgroup, is_shutdown=True).order_by('start_time').last() # 找到最后一次停机记录
|
||||||
if last_stlog:
|
if last_stlog:
|
||||||
if mplog.tag_update >= last_stlog.start_time: # 认为是有效信号
|
if mplog.tag_update >= last_stlog.start_time: # 认为是有效信号
|
||||||
if last_stlog.end_time is None and mplog.tag_val==1:
|
if last_stlog.end_time is None and mplog.tag_val == 1: # 从停到开
|
||||||
last_stlog.end_time = mplog.tag_update
|
last_stlog.end_time = mplog.tag_update
|
||||||
last_stlog.duration = (last_stlog.end_time - last_stlog.start_time).total_seconds()/3600
|
last_stlog.duration = (
|
||||||
|
last_stlog.end_time - last_stlog.start_time).total_seconds()/3600
|
||||||
last_stlog.save()
|
last_stlog.save()
|
||||||
mgroup.is_runing = True
|
mgroup.is_runing = True
|
||||||
mgroup.save()
|
mgroup.save()
|
||||||
cal_shut_hour(last_stlog.id) # 触发停机时间分配
|
cal_exp_duration_hour(last_stlog.id) # 触发时间分配
|
||||||
elif last_stlog.end_time and mplog.tag_val==0 and mplog.tag_update > last_stlog.end_time:
|
elif last_stlog.end_time and mplog.tag_val == 0 and mplog.tag_update > last_stlog.end_time: # 从开到停
|
||||||
StLog.objects.create(mgroup=mgroup, end_time=None, start_time=mplog.tag_update)
|
StLog.objects.create(
|
||||||
|
title='停机',
|
||||||
|
is_shutdown=True,
|
||||||
|
mgroup=mgroup,
|
||||||
|
end_time=None,
|
||||||
|
start_time=mplog.tag_update,
|
||||||
|
sflog=get_sflog(mgroup, mplog.tag_update)
|
||||||
|
)
|
||||||
mgroup.is_runing = False
|
mgroup.is_runing = False
|
||||||
mgroup.save()
|
mgroup.save()
|
||||||
else:
|
else:
|
||||||
StLog.objects.create(mgroup=mgroup, end_time=None, start_time=mplog.tag_update)
|
StLog.objects.create(
|
||||||
|
title='停机',
|
||||||
|
is_shutdown=True,
|
||||||
|
mgroup=mgroup,
|
||||||
|
end_time=None,
|
||||||
|
start_time=mplog.tag_update,
|
||||||
|
sflog=get_sflog(mgroup, mplog.tag_update))
|
||||||
mgroup.is_runing = False
|
mgroup.is_runing = False
|
||||||
mgroup.save()
|
mgroup.save()
|
||||||
|
|
|
@ -12,7 +12,7 @@ import datetime
|
||||||
from django.db.models import Sum, Avg
|
from django.db.models import Sum, Avg
|
||||||
from dateutil import tz
|
from dateutil import tz
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from apps.wpm.services import make_sflogs
|
from apps.wpm.services import get_sflog
|
||||||
from apps.mtm.models import Mgroup, Material
|
from apps.mtm.models import Mgroup, Material
|
||||||
from apps.fim.services import get_cost_unit, get_price_unit
|
from apps.fim.services import get_cost_unit, get_price_unit
|
||||||
from apps.fim.models import Fee
|
from apps.fim.models import Fee
|
||||||
|
@ -156,13 +156,7 @@ def cal_mpointstat_hour(mpointId: str, year: int, month: int, day: int, hour: in
|
||||||
mgroup = Mgroup.objects.get(id=allocate['mgroup'])
|
mgroup = Mgroup.objects.get(id=allocate['mgroup'])
|
||||||
ratio = allocate['ratio']
|
ratio = allocate['ratio']
|
||||||
# 查找并绑定值班记录
|
# 查找并绑定值班记录
|
||||||
sflog = SfLog.objects.filter(
|
sflog = get_sflog(mgroup, dt)
|
||||||
start_time__lt=dt, end_time__gte=dt, mgroup=mgroup).first()
|
|
||||||
if sflog is None: # 需要创建值班记录
|
|
||||||
make_sflogs(mgroup=mgroup, start_date=(
|
|
||||||
dt-datetime.timedelta(days=1)).date(), end_date=dt.date())
|
|
||||||
sflog = SfLog.objects.filter(
|
|
||||||
start_time__lt=dt, end_time__gte=dt, mgroup=mgroup).first()
|
|
||||||
year_s, month_s, day_s = sflog.get_ymd
|
year_s, month_s, day_s = sflog.get_ymd
|
||||||
|
|
||||||
params_hour_s = {'type': 'hour_s', 'mpoint': mpoint, 'sflog': sflog, 'mgroup': mgroup, 'year': year,
|
params_hour_s = {'type': 'hour_s', 'mpoint': mpoint, 'sflog': sflog, 'mgroup': mgroup, 'year': year,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
from apps.wpm.models import SfLog, SfLogExp, WMaterial, Mlog, Handover
|
from apps.wpm.models import SfLog, StLog, WMaterial, Mlog, Handover
|
||||||
['mgroup', 'shift', 'team', 'leader', 'team__belong_dept']
|
['mgroup', 'shift', 'team', 'leader', 'team__belong_dept']
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,27 +17,18 @@ class SfLogFilter(filters.FilterSet):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SfLogExpFilter(filters.FilterSet):
|
class StLogFilter(filters.FilterSet):
|
||||||
is_st = filters.BooleanFilter(method='filter_is_st', label='是否停机')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SfLogExp
|
model = StLog
|
||||||
fields = {
|
fields = {
|
||||||
|
"mgroup": ["exact"],
|
||||||
|
"mgroup__name": ["exact"],
|
||||||
|
"start_time": ["day", "month", "year"],
|
||||||
|
"end_time": ["isnull"],
|
||||||
"sflog": ["exact"],
|
"sflog": ["exact"],
|
||||||
"sflog__mgroup": ["exact"],
|
"sflogs": ["exact"]
|
||||||
"sflog__mgroup__name": ["exact"],
|
|
||||||
"happen_time": ["day", "month", "year"],
|
|
||||||
"sflog__end_time": ["day", "month", "year"],
|
|
||||||
"stlog": ["exact"],
|
|
||||||
"stlog__start_time": ["day", "month", "year"],
|
|
||||||
"stlog__end_time": ["day", "month", "year"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def filter_is_st(self, queryset, name, value):
|
|
||||||
if value:
|
|
||||||
return queryset.exclude(stlog=None)
|
|
||||||
return queryset.filter(stlog=None)
|
|
||||||
|
|
||||||
|
|
||||||
class WMaterialFilter(filters.FilterSet):
|
class WMaterialFilter(filters.FilterSet):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
# Generated by Django 3.2.12 on 2023-11-22 07:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('wpm', '0033_sflog_total_hour'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='cate',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='handler',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='happen_time',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='is_current_down',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='measure',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='reason',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='title',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='note',
|
||||||
|
field=models.TextField(blank=True, default='', verbose_name='处理备注'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='cate',
|
||||||
|
field=models.CharField(blank=True, max_length=10, null=True, verbose_name='原因类别'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='handler',
|
||||||
|
field=models.CharField(default='', max_length=100, verbose_name='处理人'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='is_shutdown',
|
||||||
|
field=models.BooleanField(default=False, verbose_name='是否是停机'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='measure',
|
||||||
|
field=models.TextField(default='', max_length=100, verbose_name='处置措施'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='reason',
|
||||||
|
field=models.TextField(default='', max_length=100, verbose_name='事件原因'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='sflog',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='wpm.sflog', verbose_name='发生时所在值班'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='sflogs',
|
||||||
|
field=models.ManyToManyField(related_name='stlog_sflogs', through='wpm.SfLogExp', to='wpm.SfLog', verbose_name='关联所有当班'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='title',
|
||||||
|
field=models.CharField(default='', max_length=20, verbose_name='异常名称'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='sflog',
|
||||||
|
name='stlogs',
|
||||||
|
field=models.ManyToManyField(related_name='sflog_stlogs', through='wpm.SfLogExp', to='wpm.StLog', verbose_name='关联异常记录'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='duration',
|
||||||
|
field=models.FloatField(blank=True, null=True, verbose_name='持续时长(h)'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='sflogexp',
|
||||||
|
name='stlog',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.stlog', verbose_name='关联异常记录'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='duration',
|
||||||
|
field=models.FloatField(blank=True, null=True, verbose_name='持续时间(h)'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='end_time',
|
||||||
|
field=models.DateTimeField(blank=True, null=True, verbose_name='结束时间'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='stlog',
|
||||||
|
name='start_time',
|
||||||
|
field=models.DateTimeField(verbose_name='发生时间'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -10,17 +10,6 @@ from apps.system.models import Dept
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
|
||||||
class StLog(CommonADModel):
|
|
||||||
"""
|
|
||||||
停机记录
|
|
||||||
"""
|
|
||||||
mgroup = models.ForeignKey(
|
|
||||||
Mgroup, verbose_name='关联工段', on_delete=models.CASCADE)
|
|
||||||
start_time = models.DateTimeField('停机开始')
|
|
||||||
end_time = models.DateTimeField('停机结束', null=True, blank=True)
|
|
||||||
duration = models.FloatField('停机时长(h)', null=True, blank=True)
|
|
||||||
|
|
||||||
|
|
||||||
class SfLog(CommonADModel):
|
class SfLog(CommonADModel):
|
||||||
"""值班记录
|
"""值班记录
|
||||||
"""
|
"""
|
||||||
|
@ -37,7 +26,7 @@ class SfLog(CommonADModel):
|
||||||
end_time = models.DateTimeField('值班结束')
|
end_time = models.DateTimeField('值班结束')
|
||||||
note = models.TextField('其他备注', null=True, blank=True)
|
note = models.TextField('其他备注', null=True, blank=True)
|
||||||
stlogs = models.ManyToManyField(
|
stlogs = models.ManyToManyField(
|
||||||
'wpm.stlog', verbose_name='关联停机记录', through='wpm.sflogexp')
|
'wpm.stlog', verbose_name='关联异常记录', through='wpm.sflogexp', related_name='sflog_stlogs')
|
||||||
last_test_time = models.DateTimeField('最后质检时间', null=True, blank=True)
|
last_test_time = models.DateTimeField('最后质检时间', null=True, blank=True)
|
||||||
total_hour_now = models.FloatField('总时长动', default=0)
|
total_hour_now = models.FloatField('总时长动', default=0)
|
||||||
total_hour = models.FloatField('总时长', default=12)
|
total_hour = models.FloatField('总时长', default=12)
|
||||||
|
@ -53,22 +42,37 @@ class SfLog(CommonADModel):
|
||||||
return end_time_local.year, end_time_local.month, end_time_local.day
|
return end_time_local.year, end_time_local.month, end_time_local.day
|
||||||
|
|
||||||
|
|
||||||
class SfLogExp(CommonADModel):
|
class StLog(CommonADModel):
|
||||||
"""
|
"""
|
||||||
生产异常情况记录
|
异常记录
|
||||||
"""
|
"""
|
||||||
|
title = models.CharField('异常名称', max_length=20, default='')
|
||||||
|
is_shutdown = models.BooleanField('是否是停机', default=False)
|
||||||
|
mgroup = models.ForeignKey(
|
||||||
|
Mgroup, verbose_name='关联工段', on_delete=models.CASCADE)
|
||||||
sflog = models.ForeignKey(
|
sflog = models.ForeignKey(
|
||||||
SfLog, on_delete=models.CASCADE, verbose_name='关联值班记录')
|
SfLog, on_delete=models.CASCADE, verbose_name='发生时所在值班', null=True, blank=True)
|
||||||
stlog = models.ForeignKey(
|
sflogs = models.ManyToManyField(
|
||||||
StLog, verbose_name='关联停机记录', on_delete=models.CASCADE, null=True, blank=True)
|
'wpm.sflog', verbose_name='关联所有当班', through='wpm.sflogexp', related_name='stlog_sflogs')
|
||||||
title = models.CharField('异常名称', max_length=20)
|
start_time = models.DateTimeField('发生时间')
|
||||||
happen_time = models.DateTimeField('发生时间', null=True, blank=True)
|
end_time = models.DateTimeField('结束时间', null=True, blank=True)
|
||||||
|
duration = models.FloatField('持续时间(h)', null=True, blank=True)
|
||||||
cate = models.CharField('原因类别', max_length=10, null=True, blank=True)
|
cate = models.CharField('原因类别', max_length=10, null=True, blank=True)
|
||||||
reason = models.TextField('事件原因', default='', max_length=100)
|
reason = models.TextField('事件原因', default='', max_length=100)
|
||||||
measure = models.TextField('处置措施', default='', max_length=100)
|
measure = models.TextField('处置措施', default='', max_length=100)
|
||||||
handler = models.CharField('处理人', default='', max_length=100)
|
handler = models.CharField('处理人', default='', max_length=100)
|
||||||
is_current_down = models.BooleanField('是否本班停机', default=False)
|
|
||||||
duration = models.FloatField('停机时长(h)', null=True, blank=True)
|
|
||||||
|
class SfLogExp(CommonADModel):
|
||||||
|
"""
|
||||||
|
异常处理
|
||||||
|
"""
|
||||||
|
sflog = models.ForeignKey(
|
||||||
|
SfLog, on_delete=models.CASCADE, verbose_name='关联值班记录')
|
||||||
|
stlog = models.ForeignKey(
|
||||||
|
StLog, verbose_name='关联异常记录', on_delete=models.CASCADE)
|
||||||
|
duration = models.FloatField('持续时长(h)', null=True, blank=True)
|
||||||
|
note = models.TextField('处理备注', default='', blank=True)
|
||||||
|
|
||||||
|
|
||||||
class WMaterial(CommonBDModel):
|
class WMaterial(CommonBDModel):
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
from apps.utils.constants import EXCLUDE_FIELDS
|
from apps.utils.constants import EXCLUDE_FIELDS
|
||||||
from apps.utils.serializers import CustomModelSerializer
|
from apps.utils.serializers import CustomModelSerializer
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError, ParseError
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog
|
from .models import SfLog, StLog, SfLogExp, WMaterial, Mlog, Handover, Mlogb, AttLog
|
||||||
from apps.system.models import Dept, User
|
from apps.system.models import Dept, User
|
||||||
from apps.system.serializers import UserSimpleSerializer
|
from apps.system.serializers import UserSimpleSerializer
|
||||||
from apps.pm.models import Mtask
|
from apps.pm.models import Mtask
|
||||||
from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change
|
from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change, cal_exp_duration_hour
|
||||||
|
from apps.wpm.services import get_sflog
|
||||||
from apps.mtm.models import Mgroup, TeamMember, Shift
|
from apps.mtm.models import Mgroup, TeamMember, Shift
|
||||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
@ -16,10 +18,62 @@ from django.utils import timezone
|
||||||
|
|
||||||
class StLogSerializer(CustomModelSerializer):
|
class StLogSerializer(CustomModelSerializer):
|
||||||
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
|
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
|
||||||
|
current_sflog = serializers.CharField(label='当前处理值班', write_only=True)
|
||||||
|
current_note = serializers.CharField(
|
||||||
|
label='值班处理备注', write_only=True, allow_blank=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StLog
|
model = StLog
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
read_only_fields = EXCLUDE_FIELDS + \
|
||||||
|
['is_shutdown', 'sflog', 'duration']
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
current_sflog = validated_data.pop('current_sflog')
|
||||||
|
current_note = validated_data.pop('note', '')
|
||||||
|
with transaction.atomic():
|
||||||
|
validated_data['sflog'] = get_sflog(
|
||||||
|
validated_data['mgroup'], validated_data['start_time'])
|
||||||
|
if current_sflog != validated_data['sflog']:
|
||||||
|
raise ParseError('值班时间与发生时间不一致')
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
SfLogExp.objects.create(
|
||||||
|
sflog=current_sflog, stlog=instance, create_by=self.context['request'].user, note=current_note)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
if instance.is_shutdown: # 停机不可编辑end_time
|
||||||
|
validated_data.pop('end_time', None)
|
||||||
|
if instance.end_time:
|
||||||
|
raise ParseError('该异常已结束无需编辑')
|
||||||
|
with transaction.atomic():
|
||||||
|
validated_data.pop('mgroup', None)
|
||||||
|
validated_data.pop('start_time', None)
|
||||||
|
end_time = validated_data.pop('end_time', None)
|
||||||
|
if end_time: # 需要把涉及到的sflog都拉入
|
||||||
|
cal_exp_duration_hour(instance.id)
|
||||||
|
current_sflog = validated_data.pop('current_sflog')
|
||||||
|
current_note = validated_data.pop('current_note', '')
|
||||||
|
instance = super().update(instance, validated_data)
|
||||||
|
try:
|
||||||
|
sflogexp = SfLogExp.objects.get(
|
||||||
|
stlog=instance.stlog, sflog=current_sflog)
|
||||||
|
sflogexp.note = current_note
|
||||||
|
sflogexp.save()
|
||||||
|
except SfLogExp.DoesNotExist:
|
||||||
|
raise ParseError('该异常无需本班填写')
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
start_time: datetime = attrs['start_time']
|
||||||
|
end_time: datetime = attrs.get('end_time', None)
|
||||||
|
if end_time:
|
||||||
|
if end_time > start_time:
|
||||||
|
attrs['duration'] = (
|
||||||
|
end_time - start_time).total_seconds / 3600
|
||||||
|
else:
|
||||||
|
raise ParseError('结束时间应大于开始时间')
|
||||||
|
return super().validate(attrs)
|
||||||
|
|
||||||
|
|
||||||
class SfLogSerializer(CustomModelSerializer):
|
class SfLogSerializer(CustomModelSerializer):
|
||||||
|
@ -68,17 +122,17 @@ class SfLogSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class SflogExpSerializer(CustomModelSerializer):
|
class SflogExpSerializer(CustomModelSerializer):
|
||||||
mgroup = serializers.CharField(source='sflog.mgroup.id', read_only=True)
|
# mgroup = serializers.CharField(source='sflog.mgroup.id', read_only=True)
|
||||||
mgroup_name = serializers.CharField(
|
# mgroup_name = serializers.CharField(
|
||||||
source='sflog.mgroup.name', read_only=True)
|
# source='sflog.mgroup.name', read_only=True)
|
||||||
stlog_ = StLogSerializer(source='stlog', read_only=True)
|
# stlog_ = StLogSerializer(source='stlog', read_only=True)
|
||||||
happen_time = serializers.DateTimeField(required=True, label='发生时间')
|
# happen_time = serializers.DateTimeField(required=True, label='发生时间')
|
||||||
cate = serializers.CharField(required=True, label='原因类别')
|
# cate = serializers.CharField(required=True, label='原因类别')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SfLogExp
|
model = SfLogExp
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
read_only_fields = EXCLUDE_FIELDS + ['stlog', 'is_current_down']
|
read_only_fields = EXCLUDE_FIELDS + ['sflog', 'stlog', 'duration']
|
||||||
|
|
||||||
|
|
||||||
class WMaterialSerializer(CustomModelSerializer):
|
class WMaterialSerializer(CustomModelSerializer):
|
||||||
|
|
|
@ -16,6 +16,17 @@ from apps.mtm.models import Mgroup, Shift, Material, Route
|
||||||
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
|
from .models import SfLog, SfLogExp, WMaterial, Mlog, Mlogb, Handover
|
||||||
|
|
||||||
|
|
||||||
|
def get_sflog(mgroup: Mgroup, happen_time: datetime):
|
||||||
|
sflog = SfLog.objects.filter(
|
||||||
|
start_time__lt=happen_time, end_time__gte=happen_time, mgroup=mgroup).first()
|
||||||
|
if sflog is None: # 需要创建值班记录
|
||||||
|
make_sflogs(mgroup=mgroup, start_date=(
|
||||||
|
happen_time-datetime.timedelta(days=1)).date(), end_date=happen_time.date())
|
||||||
|
sflog = SfLog.objects.filter(
|
||||||
|
start_time__lt=happen_time, end_time__gte=happen_time, mgroup=mgroup).first()
|
||||||
|
return sflog
|
||||||
|
|
||||||
|
|
||||||
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date, create_by=None):
|
def make_sflogs(mgroup: Mgroup, start_date: datetime.date, end_date: datetime.date, create_by=None):
|
||||||
shift_rule = mgroup.shift_rule
|
shift_rule = mgroup.shift_rule
|
||||||
shifts = Shift.objects.filter(rule=shift_rule) # 根据排班规则制定排班记录
|
shifts = Shift.objects.filter(rule=shift_rule) # 根据排班规则制定排班记录
|
||||||
|
|
|
@ -58,33 +58,34 @@ def get_total_hour_now(sflogId: str):
|
||||||
|
|
||||||
|
|
||||||
@shared_task(base=CustomTask)
|
@shared_task(base=CustomTask)
|
||||||
def cal_shut_hour(stlogId: str):
|
def cal_exp_duration_hour(stlogId: str):
|
||||||
"""
|
"""
|
||||||
计算停机记录对应的班停时长
|
计算异常记录对应的每班持续时间
|
||||||
"""
|
"""
|
||||||
from apps.enm.tasks import cal_enstat
|
from apps.enm.tasks import cal_enstat # 如果是停机需要进行统计停机时长
|
||||||
if stlogId:
|
if stlogId:
|
||||||
stlogs = StLog.objects.filter(id=stlogId)
|
stlogs = StLog.objects.filter(id=stlogId)
|
||||||
else:
|
else: # 不传就默认更新所有的
|
||||||
stlogs = StLog.objects.filter(end_time=None)
|
stlogs = StLog.objects.filter(end_time=None)
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
for stlog in stlogs:
|
for stlog in stlogs:
|
||||||
|
need_cal_enstat = True
|
||||||
|
if stlog.is_shutdown is False:
|
||||||
|
need_cal_enstat = False
|
||||||
st_start = stlog.start_time
|
st_start = stlog.start_time
|
||||||
if st_start >= now:
|
if st_start >= now:
|
||||||
break
|
break
|
||||||
if stlog.end_time is None: # 说明停机还未结束,此时也需要计算duration
|
if stlog.end_time is None: # 说明异常还未结束,此时也需要计算duration
|
||||||
st_end = now
|
st_end = now
|
||||||
else:
|
else:
|
||||||
st_end = stlog.end_time
|
st_end = stlog.end_time
|
||||||
sf_qs = SfLog.objects.filter(mgroup=stlog.mgroup)
|
sf_qs = SfLog.objects.filter(mgroup=stlog.mgroup)
|
||||||
sf_qs = (sf_qs.filter(start_time__gte=st_start, start_time__lt=st_end) | sf_qs.filter(end_time__gt=st_start,
|
sf_qs = (sf_qs.filter(start_time__gte=st_start, start_time__lt=st_end) | sf_qs.filter(end_time__gt=st_start,
|
||||||
end_time__lte=st_end) | sf_qs.filter(start_time__lte=st_start, end_time__gte=st_end)).order_by('start_time').distinct()
|
end_time__lte=st_end) | sf_qs.filter(start_time__lte=st_start, end_time__gte=st_end)).order_by('start_time').distinct()
|
||||||
|
SfLogExp.objects.filter(stlog=stlog, sflog__in=sf_qs).delete()
|
||||||
for ind, sflog in enumerate(sf_qs):
|
for ind, sflog in enumerate(sf_qs):
|
||||||
is_current_down = False
|
|
||||||
if ind == 0:
|
|
||||||
is_current_down = True
|
|
||||||
sflogexp, _ = SfLogExp.objects.get_or_create(stlog=stlog, sflog=sflog, defaults={
|
sflogexp, _ = SfLogExp.objects.get_or_create(stlog=stlog, sflog=sflog, defaults={
|
||||||
'stlog': stlog, 'sflog': sflog, 'is_current_down': is_current_down, 'title': '停机'})
|
'stlog': stlog, 'sflog': sflog})
|
||||||
# 计算duration
|
# 计算duration
|
||||||
sf_end, sf_start = sflog.end_time, sflog.start_time
|
sf_end, sf_start = sflog.end_time, sflog.start_time
|
||||||
duration_item_delta = min(sf_end, st_end) - max(sf_start, st_start)
|
duration_item_delta = min(sf_end, st_end) - max(sf_start, st_start)
|
||||||
|
@ -95,9 +96,10 @@ def cal_shut_hour(stlogId: str):
|
||||||
duration_item = total_seconds/3600
|
duration_item = total_seconds/3600
|
||||||
sflogexp.duration = duration_item
|
sflogexp.duration = duration_item
|
||||||
sflogexp.save()
|
sflogexp.save()
|
||||||
|
if need_cal_enstat:
|
||||||
# 计算每班的总停机时间
|
# 计算每班的总停机时间
|
||||||
ret = SfLogExp.objects.filter(sflog=sflog).exclude(
|
ret = SfLogExp.objects.filter(
|
||||||
stlog=None).aggregate(sum=Sum('duration'))
|
sflog=sflog, stlog__is_shutdown=True).aggregate(sum=Sum('duration'))
|
||||||
if ret.get('sum', 0):
|
if ret.get('sum', 0):
|
||||||
sflog.shut_hour = ret['sum']
|
sflog.shut_hour = ret['sum']
|
||||||
sflog.save()
|
sflog.save()
|
||||||
|
|
|
@ -13,7 +13,7 @@ from apps.pm.models import Mtask
|
||||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||||
from apps.utils.mixins import BulkCreateModelMixin
|
from apps.utils.mixins import BulkCreateModelMixin
|
||||||
|
|
||||||
from .filters import SfLogExpFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter
|
from .filters import StLogFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter
|
||||||
from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog
|
from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog
|
||||||
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer,
|
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer,
|
||||||
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
|
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
|
||||||
|
@ -22,19 +22,24 @@ from .services import mlog_submit, update_mtask, handover_submit
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
|
||||||
class StLogViewSet(ListModelMixin, CustomGenericViewSet):
|
class StLogViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
list:停机记录
|
list:异常记录
|
||||||
|
|
||||||
停机记录
|
异常记录
|
||||||
"""
|
"""
|
||||||
perms_map = {'get': '*'}
|
|
||||||
queryset = StLog.objects.all()
|
queryset = StLog.objects.all()
|
||||||
serializer_class = StLogSerializer
|
serializer_class = StLogSerializer
|
||||||
select_related_fields = ['mgroup']
|
select_related_fields = ['mgroup']
|
||||||
filterset_fields = ['mgroup']
|
filterset_class = StLogFilter
|
||||||
ordering = ['-start_time']
|
ordering = ['-start_time']
|
||||||
|
|
||||||
|
def destroy(self, request, *args, **kwargs):
|
||||||
|
obj: StLog = self.get_object()
|
||||||
|
if obj.is_shutdown:
|
||||||
|
raise ParseError('停机记录不可删除')
|
||||||
|
return super().destroy(request, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SfLogViewSet(UpdateModelMixin, ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
class SfLogViewSet(UpdateModelMixin, ListModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
|
@ -76,16 +81,16 @@ class SfLogViewSet(UpdateModelMixin, ListModelMixin, DestroyModelMixin, CustomGe
|
||||||
return Response(sr.data)
|
return Response(sr.data)
|
||||||
|
|
||||||
|
|
||||||
class SfLogExpViewSet(CustomModelViewSet):
|
class SfLogExpViewSet(ListModelMixin, UpdateModelMixin, CustomGenericViewSet):
|
||||||
"""
|
"""
|
||||||
list:生产异常动态
|
list:异常值班处理
|
||||||
|
|
||||||
生产异常动态
|
异常值班处理
|
||||||
"""
|
"""
|
||||||
queryset = SfLogExp.objects.all()
|
queryset = SfLogExp.objects.all()
|
||||||
serializer_class = SflogExpSerializer
|
serializer_class = SflogExpSerializer
|
||||||
select_related_fields = ['sflog', 'sflog__mgroup', 'stlog']
|
select_related_fields = ['sflog', 'sflog__mgroup', 'stlog']
|
||||||
filterset_class = SfLogExpFilter
|
filterset_fields = ['sflog', 'stlog']
|
||||||
|
|
||||||
|
|
||||||
class WMaterialViewSet(ListModelMixin, CustomGenericViewSet):
|
class WMaterialViewSet(ListModelMixin, CustomGenericViewSet):
|
||||||
|
|
Loading…
Reference in New Issue