146 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
	
	
from rest_framework.decorators import action
 | 
						||
from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet
 | 
						||
from apps.utils.mixins import CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin
 | 
						||
 | 
						||
from apps.wpmw.models import Wpr, WprDefect
 | 
						||
from apps.wpmw.serializers import WprSerializer, WprNewSerializer, WprDetailSerializer, WproutListSerializer, WprChangeNumberSerializer
 | 
						||
from rest_framework.response import Response
 | 
						||
from apps.mtm.models import Material
 | 
						||
from rest_framework.exceptions import ParseError
 | 
						||
from django.db import transaction
 | 
						||
from apps.wpmw.filters import WprFilter
 | 
						||
from apps.utils.sql import query_one_dict
 | 
						||
from django.db.models.expressions import RawSQL
 | 
						||
 | 
						||
 | 
						||
class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, CustomGenericViewSet):
 | 
						||
    """动态产品
 | 
						||
 | 
						||
    动态产品
 | 
						||
    """
 | 
						||
 | 
						||
    perms_map = {"get": "*"}
 | 
						||
    select_related_fields = ["wm", "mb", "material", "wm__material_ofrom"]
 | 
						||
    prefetch_related_fields = ["defects"]
 | 
						||
    queryset = Wpr.objects.all()
 | 
						||
    serializer_class = WprSerializer
 | 
						||
    retrieve_serializer_class = WprDetailSerializer
 | 
						||
    filterset_class = WprFilter
 | 
						||
    ordering = ["number", "create_time"]
 | 
						||
    ordering_fields = ["number", "create_time", "update_time"]
 | 
						||
    search_fields = ["number", "material__name", "material__model", "material__specification", "number_out"]
 | 
						||
    annotate_dict = {
 | 
						||
        "number_prefix": RawSQL("regexp_replace(number, '(\\d+)$', '')", []),
 | 
						||
        "number_suffix": RawSQL("COALESCE(NULLIF(regexp_replace(number, '.*?(\\d+)$', '\\1'), ''), '0')::bigint", []),
 | 
						||
    }
 | 
						||
 | 
						||
    def filter_queryset(self, queryset):
 | 
						||
        qs = super().filter_queryset(queryset)
 | 
						||
        if "mb__isnull" in self.request.query_params or "wm__isnull" in self.request.query_params:
 | 
						||
            pass
 | 
						||
        else:
 | 
						||
            qs.exclude(mb=None, wm=None)
 | 
						||
        return qs
 | 
						||
    
 | 
						||
    @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WprChangeNumberSerializer)
 | 
						||
    @transaction.atomic
 | 
						||
    def change_number(self, request, *args, **kwargs):
 | 
						||
        """修改编号"""
 | 
						||
        sr = WprChangeNumberSerializer(data=request.data)
 | 
						||
        sr.is_valid(raise_exception=True)
 | 
						||
        vdata = sr.validated_data
 | 
						||
        new_number = vdata["new_number"]
 | 
						||
        old_number = vdata["old_number"]
 | 
						||
        if Wpr.objects.filter(number=new_number).exists():
 | 
						||
            raise ParseError("新编号已存在,不可使用")
 | 
						||
        wpr = Wpr.objects.get(number=old_number)
 | 
						||
        from apps.wpm.models import Mlogbw, Handoverbw
 | 
						||
        from apps.inm.models import MIOItemw
 | 
						||
        Wpr.objects.filter(id=wpr.id).update(number=new_number)
 | 
						||
        Mlogbw.objects.filter(wpr=wpr).update(number=new_number)
 | 
						||
        Handoverbw.objects.filter(wpr=wpr).update(number=new_number)
 | 
						||
        MIOItemw.objects.filter(wpr=wpr).update(number=new_number)
 | 
						||
        return Response()
 | 
						||
 | 
						||
    @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WprNewSerializer)
 | 
						||
    def new_number(self, request, *args, **kwargs):
 | 
						||
        """获取新的编号"""
 | 
						||
        data = request.data
 | 
						||
        year = data.get("year")
 | 
						||
        month = data.get("month")
 | 
						||
        material_start = data.get("material_start")
 | 
						||
        wps_qs = Wpr.objects.filter(material_start=material_start, create_time__year=year, create_time__month=month).order_by("create_time")
 | 
						||
        wpr_last = wps_qs.order_by("number").last()
 | 
						||
        count = wps_qs.count()
 | 
						||
        last_number = wpr_last.number if count > 0 else None
 | 
						||
        last_number_count = int(last_number.split("-")[-1].lstrip("0"))
 | 
						||
        mat = Material.objects.get(id=material_start)
 | 
						||
        return Response({"count": count, "last_number": last_number, "material_model": mat.model, "last_number_count": last_number_count})
 | 
						||
 | 
						||
    @action(methods=["get"], detail=False, perms_map={"get": "*"})
 | 
						||
    def number_out_last(self, request, *args, **kwargs):
 | 
						||
        """获取最新的出库对外编号
 | 
						||
 | 
						||
        获取最新的出库对外编号(get请求传入prefix参数和with_unsubmit参数,with_unsubmit默认为yes,表示是否包含未出库的记录,prefix为前缀,如'WPR-2023-0)"""
 | 
						||
        from apps.inm.models import MIOItemw
 | 
						||
 | 
						||
        prefix = request.query_params.get("prefix", None)
 | 
						||
        if not prefix:
 | 
						||
            raise ParseError("请传入前缀参数")
 | 
						||
        with_unsubmit = request.query_params.get("with_unsubmit", "yes")
 | 
						||
        # wpr_qs_last = Wpr.objects.filter(number_out__startswith=prefix).order_by("number_out").last()
 | 
						||
        # 使用原始sql
 | 
						||
        query = """
 | 
						||
                SELECT id, number_out FROM wpmw_wpr 
 | 
						||
                WHERE number_out ~ %s order by number_out desc limit 1
 | 
						||
                """
 | 
						||
        pattern = f"^{prefix}[0-9]+$"
 | 
						||
        number_outs = []
 | 
						||
        wpr_qs_last = query_one_dict(query, [pattern])
 | 
						||
        if wpr_qs_last:
 | 
						||
            number_outs.append(wpr_qs_last["number_out"])
 | 
						||
        # 查找未出库的记录
 | 
						||
        if with_unsubmit == "yes":
 | 
						||
            # mioitemw_last = MIOItemw.objects.filter(
 | 
						||
            #     number_out__isnull=False, number_out__startswith=prefix).order_by("number_out").last()
 | 
						||
            query2 = """
 | 
						||
                select mioitemw.id, mioitemw.number_out from inm_mioitemw mioitemw left join inm_mioitem mioitem on mioitem.id = mioitemw.mioitem_id
 | 
						||
                left join inm_mio mio on mio.id = mioitem.mio_id
 | 
						||
                where mio.submit_time is null and mioitemw.number_out ~ %s order by mioitemw.number_out desc limit 1
 | 
						||
                    """
 | 
						||
            mioitemw_last = query_one_dict(query2, [pattern])
 | 
						||
            if mioitemw_last:
 | 
						||
                number_outs.append(mioitemw_last["number_out"])
 | 
						||
        if number_outs:
 | 
						||
            number_outs.sort()
 | 
						||
            number_out_last = number_outs[-1]
 | 
						||
            number_int_last = number_out_last.lstrip(prefix).lstrip("0")
 | 
						||
            try:
 | 
						||
                number_int_last = int(number_int_last)
 | 
						||
            except ValueError:
 | 
						||
                raise ParseError(f"找到 {number_int_last}, 请检查前缀格式")
 | 
						||
            return Response({"number_out_last": number_out_last, "number_out_int_last": int(number_int_last)})
 | 
						||
        else:
 | 
						||
            return Response({"number_out_last": None})
 | 
						||
 | 
						||
    @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WproutListSerializer)
 | 
						||
    @transaction.atomic
 | 
						||
    def assgin_number_out(self, request, *args, **kwargs):
 | 
						||
        """分配出库对外编号
 | 
						||
 | 
						||
        分配出库对外编号"""
 | 
						||
        sr = WproutListSerializer(data=request.data)
 | 
						||
        sr.is_valid(raise_exception=True)
 | 
						||
        vdata = sr.validated_data
 | 
						||
        items = vdata["items"]
 | 
						||
        number_outs = [i["number_out"] for i in items]
 | 
						||
        existing_numbers = Wpr.objects.filter(number_out__in=number_outs, number_out__isnull=False).values_list("number_out", flat=True)
 | 
						||
        if existing_numbers.exists():
 | 
						||
            used_numbers = list(existing_numbers)
 | 
						||
            raise ParseError(f"以下对外编号已被使用: {used_numbers[0]} 共{len(used_numbers)}个")
 | 
						||
        for i in items:
 | 
						||
            wpr = Wpr.objects.get(id=i["id"])
 | 
						||
            wpr.number_out = i["number_out"]
 | 
						||
            wpr.save()
 | 
						||
        return Response()
 |