Compare commits

...

2 Commits

Author SHA1 Message Date
caoqianming 0c1e93bf0b feat: 添加wpr查询参数 2025-09-29 14:50:02 +08:00
caoqianming 5d3c4137fe feat: base cquery支持annotate 2025-09-29 14:44:08 +08:00
3 changed files with 35 additions and 14 deletions

View File

@ -243,6 +243,8 @@ class ComplexQueryMixin:
vdata = sr.validated_data vdata = sr.validated_data
queryset = self.get_queryset() queryset = self.get_queryset()
querys = vdata.get('querys', []) querys = vdata.get('querys', [])
annotate_field_list = vdata.get('annotate_field_list', [])
if not querys: if not querys:
new_qs = queryset new_qs = queryset
else: else:
@ -264,17 +266,29 @@ class ComplexQueryMixin:
new_qs = new_qs | one_qs new_qs = new_qs | one_qs
except Exception as e: except Exception as e:
raise ParseError(str(e)) raise ParseError(str(e))
if annotate_field_list:
annotate_dict = getattr(self, "annotate_dict", {})
if annotate_dict:
filtered_annotate_dict = { key: annotate_dict[key] for key in annotate_field_list if key in annotate_dict}
new_qs = new_qs.annotate(**filtered_annotate_dict)
ordering = vdata.get('ordering', None) ordering = vdata.get('ordering', None)
if not ordering: if not ordering:
ordering = getattr(self, 'ordering', None) ordering = getattr(self, 'ordering', None)
if isinstance(ordering, str): if isinstance(ordering, str):
ordering = ordering.replace('\n', '').replace(' ', '')
ordering = ordering.split(',') ordering = ordering.split(',')
order_fields = []
if ordering: if ordering:
for item in ordering: for item in ordering:
if item.startswith('-'): if item.startswith('-'):
new_qs = new_qs.order_by(F(item[1:]).desc(nulls_last=True)) # JSONField 排序只能用字符串,不要 F
order_fields.append(F(item[1:]).desc(nulls_last=True) if '__' not in item else item)
else: else:
new_qs = new_qs.order_by(item) order_fields.append(F(item).asc(nulls_last=True) if '__' not in item else item)
new_qs = new_qs.order_by(*order_fields)
page = self.paginate_queryset(new_qs) page = self.paginate_queryset(new_qs)
if page is not None: if page is not None:
serializer = self.get_serializer(page, many=True) serializer = self.get_serializer(page, many=True)

View File

@ -85,3 +85,4 @@ class ComplexSerializer(serializers.Serializer):
ordering = serializers.CharField(required=False) ordering = serializers.CharField(required=False)
querys = serializers.ListField(child=QuerySerializer( querys = serializers.ListField(child=QuerySerializer(
many=True), label="查询列表", required=False) many=True), label="查询列表", required=False)
annotate_field_list = serializers.ListField(child=serializers.CharField(), label="RawSQL字段列表", required=False)

View File

@ -10,6 +10,7 @@ from rest_framework.exceptions import ParseError
from django.db import transaction from django.db import transaction
from apps.wpmw.filters import WprFilter from apps.wpmw.filters import WprFilter
from apps.utils.sql import query_one_dict from apps.utils.sql import query_one_dict
from django.db.models.expressions import RawSQL
class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, CustomGenericViewSet): class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, CustomGenericViewSet):
@ -17,6 +18,7 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
动态产品 动态产品
""" """
perms_map = {"get": "*"} perms_map = {"get": "*"}
select_related_fields = ["wm", "mb", "material", "wm__material_ofrom"] select_related_fields = ["wm", "mb", "material", "wm__material_ofrom"]
prefetch_related_fields = ["defects"] prefetch_related_fields = ["defects"]
@ -27,6 +29,10 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
ordering = ["number", "create_time"] ordering = ["number", "create_time"]
ordering_fields = ["number", "create_time", "update_time"] ordering_fields = ["number", "create_time", "update_time"]
search_fields = ["number", "material__name", "material__model", "material__specification", "number_out"] 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): def filter_queryset(self, queryset):
qs = super().filter_queryset(queryset) qs = super().filter_queryset(queryset)
@ -36,7 +42,7 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
qs.exclude(mb=None, wm=None) qs.exclude(mb=None, wm=None)
return qs return qs
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WprNewSerializer) @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WprNewSerializer)
def new_number(self, request, *args, **kwargs): def new_number(self, request, *args, **kwargs):
"""获取新的编号""" """获取新的编号"""
data = request.data data = request.data
@ -47,16 +53,17 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
wpr_last = wps_qs.order_by("number").last() wpr_last = wps_qs.order_by("number").last()
count = wps_qs.count() count = wps_qs.count()
last_number = wpr_last.number if count > 0 else None last_number = wpr_last.number if count > 0 else None
last_number_count = int(last_number.split("-")[-1].lstrip('0')) last_number_count = int(last_number.split("-")[-1].lstrip("0"))
mat = Material.objects.get(id=material_start) 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}) 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': '*'}) @action(methods=["get"], detail=False, perms_map={"get": "*"})
def number_out_last(self, request, *args, **kwargs): def number_out_last(self, request, *args, **kwargs):
"""获取最新的出库对外编号 """获取最新的出库对外编号
获取最新的出库对外编号(get请求传入prefix参数和with_unsubmit参数with_unsubmit默认为yes表示是否包含未出库的记录prefix为前缀'WPR-2023-0)""" 获取最新的出库对外编号(get请求传入prefix参数和with_unsubmit参数with_unsubmit默认为yes表示是否包含未出库的记录prefix为前缀'WPR-2023-0)"""
from apps.inm.models import MIOItemw from apps.inm.models import MIOItemw
prefix = request.query_params.get("prefix", None) prefix = request.query_params.get("prefix", None)
if not prefix: if not prefix:
raise ParseError("请传入前缀参数") raise ParseError("请传入前缀参数")
@ -67,7 +74,7 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
SELECT id, number_out FROM wpmw_wpr SELECT id, number_out FROM wpmw_wpr
WHERE number_out ~ %s order by number_out desc limit 1 WHERE number_out ~ %s order by number_out desc limit 1
""" """
pattern = f'^{prefix}[0-9]+$' pattern = f"^{prefix}[0-9]+$"
number_outs = [] number_outs = []
wpr_qs_last = query_one_dict(query, [pattern]) wpr_qs_last = query_one_dict(query, [pattern])
if wpr_qs_last: if wpr_qs_last:
@ -87,7 +94,7 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
if number_outs: if number_outs:
number_outs.sort() number_outs.sort()
number_out_last = number_outs[-1] number_out_last = number_outs[-1]
number_int_last = number_out_last.lstrip(prefix).lstrip('0') number_int_last = number_out_last.lstrip(prefix).lstrip("0")
try: try:
number_int_last = int(number_int_last) number_int_last = int(number_int_last)
except ValueError: except ValueError:
@ -95,9 +102,8 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
return Response({"number_out_last": number_out_last, "number_out_int_last": int(number_int_last)}) return Response({"number_out_last": number_out_last, "number_out_int_last": int(number_int_last)})
else: else:
return Response({"number_out_last": None}) return Response({"number_out_last": None})
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproutListSerializer) @action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=WproutListSerializer)
@transaction.atomic @transaction.atomic
def assgin_number_out(self, request, *args, **kwargs): def assgin_number_out(self, request, *args, **kwargs):
"""分配出库对外编号 """分配出库对外编号
@ -108,7 +114,7 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
vdata = sr.validated_data vdata = sr.validated_data
items = vdata["items"] items = vdata["items"]
number_outs = [i["number_out"] for i in 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) existing_numbers = Wpr.objects.filter(number_out__in=number_outs, number_out__isnull=False).values_list("number_out", flat=True)
if existing_numbers.exists(): if existing_numbers.exists():
used_numbers = list(existing_numbers) used_numbers = list(existing_numbers)
raise ParseError(f"以下对外编号已被使用: {used_numbers[0]}{len(used_numbers)}") raise ParseError(f"以下对外编号已被使用: {used_numbers[0]}{len(used_numbers)}")
@ -116,4 +122,4 @@ class WprViewSet(CustomListModelMixin, RetrieveModelMixin, ComplexQueryMixin, Cu
wpr = Wpr.objects.get(id=i["id"]) wpr = Wpr.objects.get(id=i["id"])
wpr.number_out = i["number_out"] wpr.number_out = i["number_out"]
wpr.save() wpr.save()
return Response() return Response()