feat: material list filter low_inm优化

This commit is contained in:
caoqianming 2025-11-28 15:57:21 +08:00
parent a51494aea9
commit 8211a33b58
4 changed files with 31 additions and 26 deletions

View File

@ -2,13 +2,11 @@ from django_filters import rest_framework as filters
from apps.mtm.models import Goal, Material, Route, RoutePack from apps.mtm.models import Goal, Material, Route, RoutePack
from django.db.models.expressions import F from django.db.models.expressions import F
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from django.db.models import Sum, Q, Value, F, ExpressionWrapper, DecimalField
from django.db.models.functions import Coalesce
class MaterialFilter(filters.FilterSet): class MaterialFilter(filters.FilterSet):
tag = filters.CharFilter(method='filter_tag', label="low_inm:库存不足") tag = filters.CharFilter(method='filter_tag', label="low_inm:库存不足")
count__gt = filters.NumberFilter(field_name='count', lookup_expr='gt')
count_mb__gt = filters.NumberFilter(field_name='count_mb', lookup_expr='gt')
count_wm__gt = filters.NumberFilter(field_name='count_wm', lookup_expr='gt')
class Meta: class Meta:
model = Material model = Material
@ -30,7 +28,7 @@ class MaterialFilter(filters.FilterSet):
def filter_tag(self, queryset, name, value): def filter_tag(self, queryset, name, value):
if value == 'low_inm': if value == 'low_inm':
queryset = queryset.exclude(count_safe=None).exclude(count_safe__lte=0).filter( queryset = Material.annotate_count(queryset.exclude(count_safe=None).exclude(count_safe__lte=0)).filter(
count__lte=F('count_safe')) count__lte=F('count_safe'))
return queryset return queryset

View File

@ -6,6 +6,8 @@ from collections import defaultdict, deque
from django.db.models import Q from django.db.models import Q
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.utils import timezone from django.utils import timezone
from django.db.models import Sum, Q, Value, F, ExpressionWrapper, DecimalField
from django.db.models.functions import Coalesce
class Process(CommonBModel): class Process(CommonBModel):
""" """
@ -123,6 +125,25 @@ class Material(CommonAModel):
def fname(self): def fname(self):
return f'{self.name}|{self.specification if self.specification else ""}|{self.model if self.model else ""}|{self.process.name if self.process else ""}' return f'{self.name}|{self.specification if self.specification else ""}|{self.model if self.model else ""}|{self.process.name if self.process else ""}'
@staticmethod
def annotate_count(qs):
return qs.annotate(
count_mb=Coalesce(
Sum('mb_m__count', filter=Q(mb_m__state=10, mb_m__count__gt=0)),
Value(0),
output_field=DecimalField()
),
count_wm=Coalesce(
Sum('wm_m__count', filter=Q(wm_m__state=10, wm_m__count__gt=0)),
Value(0),
output_field=DecimalField()
)
).annotate(
count=ExpressionWrapper(
F('count_wm') + F('count_mb'),
output_field=DecimalField()
)
)
class Shift(CommonBModel): class Shift(CommonBModel):
"""TN:班次 """TN:班次

View File

@ -38,13 +38,15 @@ class MaterialSerializer(CustomModelSerializer):
count = serializers.SerializerMethodField() count = serializers.SerializerMethodField()
def get_count_mb(self, obj): def get_count_mb(self, obj):
return getattr(obj, 'count_mb', 0) return getattr(obj, 'count_mb', None)
def get_count_wm(self, obj): def get_count_wm(self, obj):
return getattr(obj, 'count_wm', 0) return getattr(obj, 'count_wm', None)
def get_count(self, obj): def get_count(self, obj):
if hasattr(obj, 'count_mb') and hasattr(obj, 'count_wm'):
return getattr(obj, 'count_mb', 0) + getattr(obj, 'count_wm', 0) return getattr(obj, 'count_mb', 0) + getattr(obj, 'count_wm', 0)
return None
class Meta: class Meta:
model = Material model = Material

View File

@ -45,23 +45,7 @@ class MaterialViewSet(CustomModelViewSet):
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
if self.action in ["list", "retrieve"] and self.request.query_params.get('wiith_count', None) == 'yes': if self.action in ["list", "retrieve"] and self.request.query_params.get('wiith_count', None) == 'yes':
return qs.annotate( return Material.annotate_count(qs)
count_mb=Coalesce(
Sum('mb_m__count', filter=Q(mb_m__state=10, mb_m__count___gt=0)),
Value(0),
output_field=DecimalField()
),
count_wm=Coalesce(
Sum('wm_m__count', filter=Q(wm_m__state=10, wm_m__count___gt=0)),
Value(0),
output_field=DecimalField()
)
).annotate(
count=ExpressionWrapper(
F('count_wm') + F('count_mb'),
output_field=DecimalField()
)
)
return qs return qs
def perform_destroy(self, instance): def perform_destroy(self, instance):