386 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
from django.shortcuts import render
 | 
						|
from django.conf import settings
 | 
						|
from rest_framework.decorators import action
 | 
						|
from rest_framework.mixins import ListModelMixin
 | 
						|
from rest_framework.response import Response
 | 
						|
from rest_framework.exceptions import ParseError
 | 
						|
 | 
						|
from apps.mtm.filters import GoalFilter, MaterialFilter, RouteFilter
 | 
						|
from apps.mtm.models import Goal, Material, Mgroup, Shift, Team, Process, Route, TeamMember, RoutePack, Srule, RouteMat
 | 
						|
from apps.mtm.serializers import (GoalSerializer, MaterialSerializer,
 | 
						|
                                  MgroupGoalYearSerializer, MgroupSerializer, MgroupDaysSerializer,
 | 
						|
                                  ShiftSerializer, TeamSerializer, ProcessSerializer, 
 | 
						|
                                  RouteSerializer, TeamMemberSerializer, RoutePackSerializer,
 | 
						|
                                  SruleSerializer, RouteMatSerializer, RoutePackCopySerializer)
 | 
						|
from apps.mtm.services import get_mgroup_goals, daoru_material, get_mgroup_days
 | 
						|
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
 | 
						|
from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin, CustomListModelMixin
 | 
						|
from rest_framework.serializers import Serializer
 | 
						|
from django.db import transaction
 | 
						|
from django.db.models import Q
 | 
						|
from apps.wf.models import Ticket
 | 
						|
from django.utils import timezone
 | 
						|
from rest_framework.permissions import IsAdminUser
 | 
						|
 | 
						|
# Create your views here.
 | 
						|
class MaterialViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list:产品
 | 
						|
 | 
						|
    产品
 | 
						|
    """
 | 
						|
    queryset = Material.objects.all()
 | 
						|
    serializer_class = MaterialSerializer
 | 
						|
    filterset_class = MaterialFilter
 | 
						|
    search_fields = ['name', 'code', 'number', 'specification', 'model']
 | 
						|
    select_related_fields = ['process']
 | 
						|
    ordering = ['name', 'model', 'specification',
 | 
						|
                'type', 'process', 'process__sort', 'sort', 'id', 'number']
 | 
						|
    ordering_fields = ['name', 'model', 'specification',
 | 
						|
                       'type', 'process', 'process__sort', 'sort', 'id', 'number']
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def perform_destroy(self, instance):
 | 
						|
        from apps.inm.models import MaterialBatch
 | 
						|
        if MaterialBatch.objects.filter(material=instance).exists():
 | 
						|
            raise ParseError('该物料有库存!')
 | 
						|
        if Route.objects.filter(Q(material=instance) | Q(material_in=instance) | Q(material_out=instance)).exists():
 | 
						|
            raise ParseError('该物料有工艺路线!')
 | 
						|
        instance.delete()
 | 
						|
        Material.objects.filter(parent=instance).update(is_deleted=True)
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, serializer_class=Serializer, perms_map={'post': 'material.create'})
 | 
						|
    @transaction.atomic
 | 
						|
    def daoru(self, request, *args, **kwargs):
 | 
						|
        """导入物料
 | 
						|
 | 
						|
        导入物料
 | 
						|
        """
 | 
						|
        daoru_material(settings.BASE_DIR + request.data.get('path', ''))
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['post'], detail=True, serializer_class=Serializer, perms_map={'post': 'material.create'})
 | 
						|
    @transaction.atomic
 | 
						|
    def cal_count(self, request, *args, **kwargs):
 | 
						|
        """统计数量
 | 
						|
 | 
						|
        统计数量
 | 
						|
        """
 | 
						|
        ins = self.get_object()
 | 
						|
        from apps.mtm.services_2 import cal_material_count
 | 
						|
        cal_material_count([ins.id])
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['put'], detail=True, serializer_class=Serializer, perms_map={'put': '*'})
 | 
						|
    @transaction.atomic
 | 
						|
    def set_week_esitimate_consume(self, request, *args, **kwargs):
 | 
						|
        """设置周预估消耗量
 | 
						|
 | 
						|
        设置周预估消耗量
 | 
						|
        """
 | 
						|
        obj: Material = self.get_object()
 | 
						|
        obj.week_esitimate_consume = request.data.get(
 | 
						|
            'week_esitimate_consume', None)
 | 
						|
        obj.save()
 | 
						|
        return Response()
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=False, serializer_class=Serializer, perms_map={'get': '*'})
 | 
						|
    def cates(self, request, *args, **kwargs):
 | 
						|
        res = Material.objects.exclude(cate='').exclude(cate=None).values_list('cate', flat=True).distinct()
 | 
						|
        return Response(set(res))
 | 
						|
 | 
						|
class ShiftViewSet(ListModelMixin, CustomGenericViewSet):
 | 
						|
    """
 | 
						|
    list:班次
 | 
						|
 | 
						|
    班次
 | 
						|
    """
 | 
						|
    perms_map = {'get': '*'}
 | 
						|
    queryset = Shift.objects.all()
 | 
						|
    serializer_class = ShiftSerializer
 | 
						|
    search_fields = ['name']
 | 
						|
    ordering = ['rule', 'sort', 'id']
 | 
						|
 | 
						|
 | 
						|
class MgroupViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list:测点集
 | 
						|
 | 
						|
    测点集
 | 
						|
    """
 | 
						|
    queryset = Mgroup.objects.all()
 | 
						|
    serializer_class = MgroupSerializer
 | 
						|
    select_related_fields = ['create_by', 'belong_dept', 'process']
 | 
						|
    filterset_fields = {
 | 
						|
        "belong_dept": ["exact"],
 | 
						|
        "process": ["exact"],
 | 
						|
        "cate": ["exact"],
 | 
						|
        "belong_dept__name": ["exact", "contains"],
 | 
						|
        "name": ["exact", "contains"],
 | 
						|
        "code": ["exact", "in", "isnull"]
 | 
						|
    }
 | 
						|
    search_fields = ['name']
 | 
						|
    ordering = ['sort', 'create_time']
 | 
						|
 | 
						|
    def perform_destroy(self, instance):
 | 
						|
        Route.objects.filter(
 | 
						|
            mgroup=instance, material__need_route=False).delete()
 | 
						|
        Route.objects.filter(mgroup=instance).update(mgroup=None)
 | 
						|
        instance.delete()
 | 
						|
    
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MgroupDaysSerializer)
 | 
						|
    def get_days(self, request):
 | 
						|
        """
 | 
						|
        获取所属班年月日
 | 
						|
 | 
						|
        给定一个时间获取所属班年月日
 | 
						|
        """
 | 
						|
        data = request.data
 | 
						|
        sr = MgroupDaysSerializer(data=data)
 | 
						|
        sr.is_valid(raise_exception=True)
 | 
						|
        vdata = sr.validated_data
 | 
						|
        mgroup = Mgroup.objects.get(id=vdata["mgroup"])
 | 
						|
        return Response(get_mgroup_days(mgroup, vdata.get("now", None)))
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class TeamViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list:班组
 | 
						|
 | 
						|
    班组
 | 
						|
    """
 | 
						|
    queryset = Team.objects.all()
 | 
						|
    serializer_class = TeamSerializer
 | 
						|
    select_related_fields = ['belong_dept', 'leader']
 | 
						|
    filterset_fields = ['belong_dept']
 | 
						|
    search_fields = ['rule']
 | 
						|
 | 
						|
 | 
						|
class TeamMemberViewSet(ListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
 | 
						|
    """
 | 
						|
    list: 班组成员
 | 
						|
 | 
						|
    班组成员
 | 
						|
    """
 | 
						|
    perms_map = {'get': '*', 'post': 'team.update', 'delete': 'team.delete'}
 | 
						|
    queryset = TeamMember.objects.all()
 | 
						|
    serializer_class = TeamMemberSerializer
 | 
						|
    select_related_fields = ['mgroup', 'post', 'team', 'user']
 | 
						|
    filterset_fields = ['mgroup', 'post', 'team']
 | 
						|
 | 
						|
 | 
						|
class GoalViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list: 目标
 | 
						|
 | 
						|
    目标
 | 
						|
    """
 | 
						|
    queryset = Goal.objects.all()
 | 
						|
    serializer_class = GoalSerializer
 | 
						|
    select_related_fields = ['mgroup', 'goal_cate']
 | 
						|
    filterset_class = GoalFilter
 | 
						|
    search_fields = ['name']
 | 
						|
    ordering = ['mgroup__sort', 'goal_cate__sort', 'goal_cate__create_time']
 | 
						|
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MgroupGoalYearSerializer)
 | 
						|
    def mgroup_goals_year(self, request, pk=None):
 | 
						|
        """
 | 
						|
        获取工段全年目标
 | 
						|
 | 
						|
        获取工段全年目标
 | 
						|
        """
 | 
						|
        sr = MgroupGoalYearSerializer(data=request.data)
 | 
						|
        sr.is_valid(raise_exception=True)
 | 
						|
        vdata = sr.validated_data
 | 
						|
        res = get_mgroup_goals(vdata['mgroup'], vdata['year'], True)
 | 
						|
        return Response(res)
 | 
						|
 | 
						|
 | 
						|
class ProcessViewSet(CustomModelViewSet):
 | 
						|
    queryset = Process.objects.all()
 | 
						|
    serializer_class = ProcessSerializer
 | 
						|
    select_related_fields = ['belong_dept']
 | 
						|
    search_fields = ['name', 'cate']
 | 
						|
    filterset_fields = {
 | 
						|
        "cate": ['exact'],
 | 
						|
        "parent": ['isnull', "exact"]
 | 
						|
    }
 | 
						|
    ordering = ['sort', 'create_time']
 | 
						|
 | 
						|
    def perform_destroy(self, instance):
 | 
						|
        if Route.objects.filter(process=instance).exists():
 | 
						|
            raise ParseError('存在使用的工艺路线!')
 | 
						|
        return super().perform_destroy(instance)
 | 
						|
 | 
						|
 | 
						|
 | 
						|
class RoutePackViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list: 工艺路线包
 | 
						|
 | 
						|
    工艺路线包
 | 
						|
    """
 | 
						|
    queryset = RoutePack.objects.all()
 | 
						|
    serializer_class = RoutePackSerializer
 | 
						|
    search_fields = ['name']
 | 
						|
    select_related_fields = ['material', 'create_by', "document"]
 | 
						|
    filterset_fields = ['material', 'state']
 | 
						|
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        obj: RoutePack = self.get_object()
 | 
						|
        if obj.state != RoutePack.RP_S_CREATE:
 | 
						|
            raise ParseError('该状态下不可编辑')
 | 
						|
        return super().update(request, *args, **kwargs)
 | 
						|
 | 
						|
    @transaction.atomic
 | 
						|
    def destroy(self, request, *args, **kwargs):
 | 
						|
        obj: RoutePack = self.get_object()
 | 
						|
        if obj.state != RoutePack.RP_S_CREATE:
 | 
						|
            raise ParseError('该状态下不可删除')
 | 
						|
        obj.delete()
 | 
						|
        Ticket.objects.filter(ticket_data__t_id=obj.id, ticket_data__t_model='routepack').delete()
 | 
						|
        return Response(status=204)
 | 
						|
    
 | 
						|
    @transaction.atomic
 | 
						|
    @action(methods=['post'], detail=False, perms_map={'post': 'routepack.create'}, serializer_class=RoutePackCopySerializer)
 | 
						|
    def copy(self, request, *args, **kwargs):
 | 
						|
        """复制工艺路线
 | 
						|
 | 
						|
        复制工艺路线
 | 
						|
        """
 | 
						|
        data = request.data
 | 
						|
        sr = RoutePackCopySerializer(data=data)
 | 
						|
        sr.is_valid(raise_exception=True)
 | 
						|
        vdata = sr.validated_data
 | 
						|
        user = request.user
 | 
						|
        now = timezone.now()
 | 
						|
        new_name = vdata["new_name"]
 | 
						|
        rp = RoutePack.objects.get(id=vdata["routepack"])
 | 
						|
        matin = Material.objects.get(id=vdata["material_in"])
 | 
						|
        matout = Material.objects.get(id=vdata["material_out"])
 | 
						|
        obj_c = RoutePack()
 | 
						|
        obj_c.name = new_name
 | 
						|
        obj_c.material = matout
 | 
						|
        obj_c.create_by = user
 | 
						|
        obj_c.create_time = now
 | 
						|
        obj_c.save()
 | 
						|
        genM = {}
 | 
						|
        for ind, route in enumerate(Route.get_routes(routepack=rp)):
 | 
						|
            route_new = Route()
 | 
						|
            process = route.process
 | 
						|
            for f in Route._meta.fields:
 | 
						|
                if f.name in ['process', 'sort', 'is_autotask', 'is_count_utask', 'out_rate', 'div_number', 'hour_work', 'batch_bind']:
 | 
						|
                    setattr(route_new, f.name, getattr(route, f.name, None))
 | 
						|
            route_new.material = matout
 | 
						|
            # material_out = RouteSerializer.gen_material_out(instance=route_new, material_out_tracking=route.material_out.tracking)
 | 
						|
            # route_new.material_out = material_out
 | 
						|
            # if ind == 0:
 | 
						|
            #     route_new.material_in = matin
 | 
						|
            # elif route.material_in.process and route.material_in.process.id in genM:
 | 
						|
            #     route_new.material_in = genM[route.material_in.process.id]
 | 
						|
            # genM[process.id] = material_out
 | 
						|
            route_new.routepack = obj_c
 | 
						|
            route_new.create_by = user
 | 
						|
            route_new.create_time = now
 | 
						|
            route_new.save()
 | 
						|
            for rm in RouteMat.objects.filter(route=route):
 | 
						|
                rm_new = RouteMat()
 | 
						|
                rm_new.route = route_new
 | 
						|
                rm_new.material = rm.material
 | 
						|
                rm_new.save()
 | 
						|
        return Response({"id": route_new.id})
 | 
						|
    
 | 
						|
    @transaction.atomic
 | 
						|
    @action(methods=['post'], detail=True, permission_classes = [IsAdminUser], serializer_class=Serializer)
 | 
						|
    def toggle_state(self, request, *args, **kwargs):
 | 
						|
        """变更工艺路线状态
 | 
						|
 | 
						|
        变更工艺路线状态
 | 
						|
        """
 | 
						|
        ins:RoutePack = self.get_object()
 | 
						|
        if  ins.state == RoutePack.RP_S_CONFIRM:
 | 
						|
            ins.state = RoutePack.RP_S_CREATE
 | 
						|
        elif ins.state == RoutePack.RP_S_CREATE:
 | 
						|
            if ins.ticket is not None:
 | 
						|
                ins.get_gjson(need_update=True)
 | 
						|
                ins.state = RoutePack.RP_S_CONFIRM
 | 
						|
            else:
 | 
						|
                raise ParseError("该路线未提交审核")
 | 
						|
        else:
 | 
						|
            raise ParseError("该状态下不可变更")
 | 
						|
        ins.save()
 | 
						|
        return Response()
 | 
						|
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get': '*'})
 | 
						|
    def dag(self, request, *args, **kwargs):
 | 
						|
        """获取总图
 | 
						|
 | 
						|
        获取总图
 | 
						|
        """
 | 
						|
        return Response(Route.get_dag(rqs=Route.objects.filter(routepack=self.get_object())))
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get': '*'})
 | 
						|
    def dags(self, request, *args, **kwargs):
 | 
						|
        """获取所有子图
 | 
						|
 | 
						|
        获取所有子图
 | 
						|
        """
 | 
						|
        ins = self.get_object()
 | 
						|
        return Response(ins.get_dags())
 | 
						|
    
 | 
						|
    @action(methods=['get'], detail=True, perms_map={'get': '*'})
 | 
						|
    def final_materials(self, request, *args, **kwargs):
 | 
						|
        """获取最终产品
 | 
						|
        
 | 
						|
        获取最终产品"""
 | 
						|
        ins:RoutePack = self.get_object()
 | 
						|
        matIds = ins.get_final_material_ids()
 | 
						|
        qs = Material.objects.filter(id__in=matIds)
 | 
						|
        res = [{"id": x.id, "name": str(x)} for x in qs]
 | 
						|
        return Response(res)
 | 
						|
class RouteViewSet(CustomModelViewSet):
 | 
						|
    queryset = Route.objects.all()
 | 
						|
    serializer_class = RouteSerializer
 | 
						|
    filterset_class = RouteFilter
 | 
						|
    ordering = ['sort', 'process__sort', 'create_time']
 | 
						|
    ordering_fields = ['sort', 'process__sort', 'create_time', 'update_time']
 | 
						|
    select_related_fields = ['material',
 | 
						|
                             'process', 'material_in', 'material_out', 'mgroup', 'routepack']
 | 
						|
 | 
						|
    def update(self, request, *args, **kwargs):
 | 
						|
        obj:Route = self.get_object()
 | 
						|
        routepack = obj.routepack
 | 
						|
        if routepack and routepack.state != RoutePack.RP_S_CREATE:
 | 
						|
            raise ParseError('该状态下不可编辑')
 | 
						|
        return super().update(request, *args, **kwargs)
 | 
						|
 | 
						|
 | 
						|
class SruleViewSet(CustomModelViewSet):
 | 
						|
    """
 | 
						|
    list: 排班规则
 | 
						|
    """
 | 
						|
    queryset = Srule.objects.all()
 | 
						|
    serializer_class = SruleSerializer
 | 
						|
    select_related_fields = ['belong_dept']
 | 
						|
    filterset_fields = ['belong_dept']
 | 
						|
    search_fields = ['belong_dept__name']
 | 
						|
    
 | 
						|
    def add_info_for_list(self, data):
 | 
						|
        rule_list = [x['rule'] for x in data]
 | 
						|
        teamIds = []
 | 
						|
        for rule in rule_list:
 | 
						|
            teamIds.extend(rule)
 | 
						|
        teams = Team.objects.filter(id__in=teamIds).values_list('id', 'name')
 | 
						|
        teams_dict = dict(teams)
 | 
						|
        for item in data:
 | 
						|
            rule = item["rule"]
 | 
						|
            item["rule_display"] = "->".join([teams_dict.get(x, '未知') for x in rule])
 | 
						|
        return data
 | 
						|
 | 
						|
class RouteMatViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
 | 
						|
    perms_map = {"get": "*", "post": "route.update", "delete": "route.update"}
 | 
						|
    queryset = RouteMat.objects.all()
 | 
						|
    serializer_class = RouteMatSerializer
 | 
						|
    filterset_fields = ['route', 'material'] |