400 lines
15 KiB
Python
400 lines
15 KiB
Python
from django.db import transaction
|
|
from django.db.models import Prefetch
|
|
from django.shortcuts import render
|
|
from rest_framework.decorators import action
|
|
from rest_framework.exceptions import ParseError
|
|
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, UpdateModelMixin
|
|
from rest_framework.response import Response
|
|
from rest_framework.serializers import Serializer
|
|
from django.db.models import Sum
|
|
from django.utils import timezone
|
|
|
|
from apps.mtm.models import Material
|
|
from apps.pm.models import Mtask
|
|
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
|
from apps.utils.mixins import BulkCreateModelMixin
|
|
|
|
from .filters import StLogFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter
|
|
from .models import SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb, AttLog, OtherLog
|
|
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogRevertSerializer,
|
|
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
|
|
GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, AttLogSerializer, OtherLogSerializer)
|
|
from .services import mlog_submit, update_mtask, handover_submit, mlog_revert
|
|
from apps.monitor.services import create_auditlog, delete_auditlog
|
|
# Create your views here.
|
|
|
|
|
|
class StLogViewSet(CustomModelViewSet):
|
|
"""
|
|
list:异常记录
|
|
|
|
异常记录
|
|
"""
|
|
queryset = StLog.objects.all()
|
|
serializer_class = StLogSerializer
|
|
select_related_fields = ['mgroup']
|
|
filterset_class = StLogFilter
|
|
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):
|
|
"""
|
|
list:值班记录
|
|
|
|
值班记录
|
|
"""
|
|
perms_map = {'get': '*', 'put': 'sflog.update', 'delete': 'sflog.delete'}
|
|
queryset = SfLog.objects.all()
|
|
serializer_class = SfLogSerializer
|
|
select_related_fields = ['mgroup', 'shift', 'team', 'leader']
|
|
filterset_class = SfLogFilter
|
|
search_fields = ['note']
|
|
ordering = ['-start_time']
|
|
|
|
@action(methods=['get'], detail=True, perms_map={'get': '*'})
|
|
def init_test(self, request, pk=None):
|
|
"""
|
|
初始化检测录入
|
|
|
|
初始化检测录入
|
|
"""
|
|
from apps.qm.models import QuaStat, TestItem
|
|
from apps.qm.serializers import QuaStatSerializer
|
|
obj = self.get_object()
|
|
test_materials = Material.objects.filter(
|
|
id__in=obj.mgroup.test_materials).order_by('sort', '-create_time')
|
|
for material in test_materials:
|
|
testitems = TestItem.objects.filter(
|
|
id__in=material.testitems).order_by('sort', '-create_time')
|
|
for testitem in testitems:
|
|
params = {'material': material,
|
|
'testitem': testitem, 'sflog': obj}
|
|
QuaStat.objects.get_or_create(
|
|
**params, defaults={**params, **{'create_by': request.user, 'belong_dept': obj.mgroup.belong_dept}})
|
|
qs = QuaStat.objects.filter(sflog=obj).order_by(
|
|
'material__sort', 'material__create_time', 'testitem__sort', 'testitem__create_time')
|
|
sr = QuaStatSerializer(instance=qs, many=True)
|
|
return Response(sr.data)
|
|
|
|
|
|
class SfLogExpViewSet(ListModelMixin, UpdateModelMixin, CustomGenericViewSet):
|
|
"""
|
|
list:异常值班处理
|
|
|
|
异常值班处理
|
|
"""
|
|
perms_map = {'get': '*', 'put': 'sflogexp.update'}
|
|
queryset = SfLogExp.objects.all()
|
|
serializer_class = SflogExpSerializer
|
|
select_related_fields = ['sflog', 'sflog__mgroup', 'stlog', 'sflog__team', 'sflog__shift', 'sflog__leader']
|
|
filterset_fields = ['sflog', 'stlog']
|
|
|
|
|
|
class WMaterialViewSet(ListModelMixin, CustomGenericViewSet):
|
|
"""
|
|
list: 车间库存
|
|
|
|
车间库存
|
|
"""
|
|
perms_map = {'get': '*'}
|
|
queryset = WMaterial.objects.all()
|
|
serializer_class = WMaterialSerializer
|
|
select_related_fields = ['material', 'belong_dept', 'material__process']
|
|
search_fields = ['material__name',
|
|
'material__number', 'material__specification']
|
|
filterset_class = WMaterialFilter
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=DeptBatchSerializer)
|
|
@transaction.atomic
|
|
def batchs(self, request):
|
|
"""获取车间的批次号(废弃)
|
|
|
|
获取车间的批次号
|
|
"""
|
|
sr = DeptBatchSerializer(data=request.data)
|
|
sr.is_valid(raise_exception=True)
|
|
vdata = sr.validated_data
|
|
batchs = WMaterial.objects.filter(
|
|
belong_dept__name=vdata['belong_dept_name'], count__gt=0).values_list('batch', flat=True).distinct()
|
|
return Response(list(batchs))
|
|
|
|
|
|
class MlogViewSet(CustomModelViewSet):
|
|
"""
|
|
list: 生产日志
|
|
|
|
生产日志
|
|
"""
|
|
queryset = Mlog.objects.all()
|
|
serializer_class = MlogSerializer
|
|
select_related_fields = ['create_by', 'update_by', 'mtask',
|
|
'handle_user', 'handle_user_2', 'equipment', 'equipment_2']
|
|
prefetch_related_fields = ['handle_users',
|
|
'material_outs', 'b_mlog', 'equipments']
|
|
filterset_class = MlogFilter
|
|
|
|
@transaction.atomic
|
|
def perform_create(self, serializer):
|
|
ins = serializer.save()
|
|
data = MlogSerializer(ins).data
|
|
create_auditlog('create', ins, data)
|
|
|
|
@transaction.atomic
|
|
def perform_destroy(self, instance):
|
|
if instance.submit_time is not None:
|
|
raise ParseError('日志已提交不可变动')
|
|
delete_auditlog(instance, instance.id)
|
|
instance.delete()
|
|
|
|
@transaction.atomic
|
|
def perform_update(self, serializer):
|
|
ins = serializer.instance
|
|
if ins.submit_time is not None:
|
|
raise ParseError('该日志已提交!')
|
|
val_old = MlogSerializer(instance=ins).data
|
|
serializer.save()
|
|
val_new = MlogSerializer(instance=ins).data
|
|
create_auditlog('update', ins, val_new, val_old)
|
|
|
|
@action(methods=['post'], detail=True, perms_map={'post': 'mlog.submit'}, serializer_class=Serializer)
|
|
@transaction.atomic
|
|
def submit(self, request, *args, **kwargs):
|
|
"""日志提交(变动车间库存)
|
|
|
|
日志提交
|
|
"""
|
|
ins: Mlog = self.get_object()
|
|
vdata_old = MlogSerializer(ins).data
|
|
now = timezone.now()
|
|
if ins.submit_time:
|
|
raise ParseError('该日志已提交!')
|
|
if ins.mtask and ins.mtask.state == Mtask.MTASK_STOP:
|
|
raise ParseError('该任务已停止!')
|
|
mlog_submit(ins, self.request.user, now)
|
|
if ins.mtask:
|
|
update_mtask(ins.mtask)
|
|
vdata_new = MlogSerializer(ins).data
|
|
create_auditlog('submit', ins, vdata_new,
|
|
vdata_old, now, self.request.user)
|
|
return Response(MlogSerializer(instance=ins).data)
|
|
|
|
@action(methods=['post'], detail=True, perms_map={'post': 'mlog.submit'}, serializer_class=MlogRevertSerializer)
|
|
@transaction.atomic
|
|
def revert(self, request, *args, **kwargs):
|
|
"""撤回日志提交
|
|
|
|
撤回日志提交
|
|
"""
|
|
ins: Mlog = self.get_object()
|
|
user = request.user
|
|
if ins.submit_time is None:
|
|
raise ParseError('日志未提交不可撤销')
|
|
if user != ins.submit_user:
|
|
raise ParseError('非提交人不可撤销!')
|
|
now = timezone.now()
|
|
mlog_revert(ins, user, now)
|
|
if ins.mtask:
|
|
mtask = ins.mtask
|
|
mtask.state = Mtask.MTASK_ASSGINED
|
|
mtask.save()
|
|
update_mtask(ins.mtask)
|
|
create_auditlog('revert', ins, {}, {}, now, user,
|
|
request.data.get('change_reason', ''))
|
|
return Response(MlogSerializer(instance=ins).data)
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MlogRelatedSerializer)
|
|
@transaction.atomic
|
|
def related_first(self, request, *args, **kwargs):
|
|
"""获取相关任务的第一道工序日志
|
|
|
|
获取相关任务的第一道工序日志
|
|
"""
|
|
sr = MlogRelatedSerializer(data=request.data)
|
|
sr.is_valid(raise_exception=True)
|
|
vdata = sr.validated_data
|
|
mtask = vdata['mtask']
|
|
if mtask.utask:
|
|
mtasks = mtask.related
|
|
mlogs = Mlog.objects.filter(mtask__in=mtasks).order_by(
|
|
'mtask__mgroup__process__sort', 'batch', 'create_time')
|
|
data = MlogSerializer(instance=mlogs, many=True).data
|
|
res_data = []
|
|
for ind, val in enumerate(data):
|
|
if ind == 0:
|
|
res_data.append(val)
|
|
else:
|
|
before = data[ind-1]
|
|
if val['batch'] != before['batch']:
|
|
res_data.append(val)
|
|
return Response(res_data)
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MlogAnaSerializer)
|
|
def ana(self, request):
|
|
"""核心统计数据
|
|
|
|
核心统计数据
|
|
"""
|
|
sr = MlogAnaSerializer(data=request.data)
|
|
sr.is_valid(raise_exception=True)
|
|
vdata = sr.validated_data
|
|
mlogs = Mlog.objects.exclude(submit_time=None)
|
|
if vdata.get('belong_dept_name', ''):
|
|
mlogs = mlogs.filter(
|
|
mgroup__belong_dept__name=vdata['belong_dept_name'])
|
|
if vdata.get('material_cate', ''):
|
|
mlogs = mlogs.filter(
|
|
material_out__cate=vdata['material_cate'])
|
|
if vdata.get('start_date', ''):
|
|
mlogs = mlogs.filter(handle_date__gte=vdata['start_date'])
|
|
if vdata.get('end_date', ''):
|
|
mlogs = mlogs.filter(handle_date__lte=vdata['end_date'])
|
|
res = mlogs.aggregate(
|
|
count_real=Sum('count_real'),
|
|
count_ok=Sum('count_ok'),
|
|
count_notok=Sum('count_notok'),
|
|
count_n_zw=Sum('count_n_zw'),
|
|
count_n_tw=Sum('count_n_tw'),
|
|
count_n_qp=Sum('count_n_qp'),
|
|
count_n_wq=Sum('count_n_wq'),
|
|
count_n_dl=Sum('count_n_dl'),
|
|
count_n_pb=Sum('count_n_pb'),
|
|
count_n_dxt=Sum('count_n_dxt'),
|
|
count_n_jsqx=Sum('count_n_jsqx'),
|
|
count_n_qt=Sum('count_n_qt'))
|
|
for i in res:
|
|
if res[i] is None:
|
|
res[i] = 0
|
|
return Response(res)
|
|
|
|
|
|
class HandoverViewSet(CustomModelViewSet):
|
|
"""
|
|
list: 交接记录
|
|
|
|
交接记录
|
|
"""
|
|
queryset = Handover.objects.all()
|
|
serializer_class = HandoverSerializer
|
|
select_related_fields = ['send_user',
|
|
'send_dept', 'recive_user', 'recive_dept']
|
|
filterset_class = HandoverFilter
|
|
|
|
def perform_destroy(self, instance):
|
|
user = self.request.user
|
|
if instance.submit_time is not None:
|
|
raise ParseError('日志已提交不可变动')
|
|
if instance.send_user != user and instance.recive_user != user and instance.create_by != user:
|
|
raise ParseError('非交送人和接收人不可删除该记录')
|
|
return super().perform_destroy(instance)
|
|
|
|
@action(methods=['post'], detail=True, perms_map={'post': 'handover.submit'}, serializer_class=Serializer)
|
|
@transaction.atomic
|
|
def submit(self, request, *args, **kwargs):
|
|
"""交接记录提交(变动车间库存)
|
|
|
|
交接记录提交
|
|
"""
|
|
ins: Handover = self.get_object()
|
|
user = self.request.user
|
|
if user != ins.recive_user:
|
|
raise ParseError('非接收人不可提交')
|
|
if ins.submit_time is None:
|
|
handover_submit(ins, user, None)
|
|
return Response()
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post': 'handover.create'}, serializer_class=GenHandoverWmSerializer)
|
|
@transaction.atomic
|
|
def gen_by_wm(self, request):
|
|
"""从车间库存生成交接记录(废弃)
|
|
|
|
从车间库存生成交接记录
|
|
"""
|
|
sr = GenHandoverWmSerializer(data=request.data)
|
|
sr.is_valid(raise_exception=True)
|
|
vdata = sr.validated_data
|
|
user = request.user
|
|
send_date, send_mgroup, send_user, recive_dept, recive_user, wm, count = vdata['send_date'], vdata['send_mgroup'], vdata[
|
|
'send_user'], vdata['recive_dept'], vdata['recive_user'], vdata['wm'], vdata['count']
|
|
if send_mgroup.belong_dept != wm.belong_dept:
|
|
raise ParseError('送料工段错误!')
|
|
handover = Handover.objects.create(
|
|
send_date=send_date,
|
|
send_user=send_user,
|
|
recive_dept=recive_dept,
|
|
recive_user=recive_user,
|
|
send_mgroup=send_mgroup,
|
|
send_dept=wm.belong_dept,
|
|
batch=wm.batch,
|
|
material=wm.material,
|
|
count=count,
|
|
wm=wm,
|
|
create_by=user
|
|
)
|
|
return Response({'handover': handover.id})
|
|
|
|
@action(methods=['post'], detail=False, perms_map={'post': 'handover.create'}, serializer_class=GenHandoverSerializer)
|
|
@transaction.atomic
|
|
def gen_by_mlog(self, request):
|
|
"""从生产日志生成交接记录(废弃)
|
|
|
|
从生产日志生成交接记录
|
|
"""
|
|
sr = GenHandoverSerializer(data=request.data)
|
|
sr.is_valid(raise_exception=True)
|
|
vdata = sr.validated_data
|
|
user = request.user
|
|
send_date, send_user, recive_dept, recive_user = vdata['send_date'], vdata[
|
|
'send_user'], vdata['recive_dept'], vdata['recive_user']
|
|
for mlog in vdata['mlogs']:
|
|
Handover.objects.create(
|
|
send_date=send_date,
|
|
send_user=send_user,
|
|
recive_dept=recive_dept,
|
|
recive_user=recive_user,
|
|
send_dept=mlog.mgroup.belong_dept,
|
|
batch=mlog.batch,
|
|
material=mlog.material_out,
|
|
count=mlog.count_real,
|
|
count_eweight=mlog.count_real_eweight,
|
|
mlog=mlog,
|
|
send_mgroup=mlog.mgroup,
|
|
create_by=user
|
|
)
|
|
return Response()
|
|
|
|
|
|
class AttlogViewSet(CustomModelViewSet):
|
|
"""
|
|
list: 车间到岗
|
|
|
|
车间到岗
|
|
"""
|
|
queryset = AttLog.objects.all()
|
|
serializer_class = AttLogSerializer
|
|
select_related_fields = ['user', 'post', 'sflog']
|
|
filterset_fields = ['sflog__mgroup',
|
|
'sflog__mgroup__belong_dept__name', 'sflog__work_date', 'sflog__mgroup__cate', 'sflog__mgroup__need_enm']
|
|
ordering = ['-sflog__work_date', 'create_time']
|
|
|
|
|
|
class OtherLogViewSet(CustomModelViewSet):
|
|
"""
|
|
list: 其他生产记录
|
|
|
|
其他生产记录
|
|
"""
|
|
queryset = OtherLog.objects.all()
|
|
serializer_class = OtherLogSerializer
|
|
filterset_fields = {
|
|
"product": ["exact"],
|
|
"handle_date": ["exact", "gte", "lte"]
|
|
}
|
|
search_fields = ['product']
|
|
ordering = ['-handle_date', '-create_time']
|