forked from erp-dev/erp
100 lines
4.0 KiB
Python
100 lines
4.0 KiB
Python
from rest_framework.generics import ListAPIView
|
||
from rest_framework import filters, serializers
|
||
from django_filters.rest_framework import DjangoFilterBackend
|
||
from django_filters import rest_framework as django_filters
|
||
|
||
from flower.viewsets import LimitedLimitOffsetPagination
|
||
from stock import models
|
||
|
||
|
||
class StockSnapshotSerializer(serializers.ModelSerializer):
|
||
"""库存快照序列化器"""
|
||
product_name = serializers.CharField(source='product.name', read_only=True)
|
||
product_code = serializers.CharField(source='product.code', read_only=True)
|
||
warehouse_name = serializers.CharField(source='warehouse.name', read_only=True)
|
||
unit_display = serializers.CharField(source='get_unit_display', read_only=True)
|
||
stock_change_record_type = serializers.CharField(
|
||
source='stock_change_record.get_type_display',
|
||
read_only=True
|
||
)
|
||
stock_change_record_source = serializers.CharField(
|
||
source='stock_change_record.get_source_type_display',
|
||
read_only=True
|
||
)
|
||
|
||
class Meta:
|
||
model = models.StockSnapshot
|
||
fields = [
|
||
'id', 'product', 'product_name', 'product_code',
|
||
'warehouse', 'warehouse_name',
|
||
'delta', 'quantity_before', 'quantity_after',
|
||
'stock_change_record', 'stock_change_record_type', 'stock_change_record_source',
|
||
'unit', 'unit_display', 'num_of_rolls',
|
||
'offset_to', 'offset_at', 'cancelled', 'cancelled_at', 'offset_id',
|
||
'created_at', 'updated_at'
|
||
]
|
||
|
||
|
||
class StockSnapshotFilterSet(django_filters.FilterSet):
|
||
"""库存快照过滤器"""
|
||
product_name = django_filters.CharFilter(field_name='product__name', lookup_expr='icontains')
|
||
product_code = django_filters.CharFilter(field_name='product__code', lookup_expr='icontains')
|
||
warehouse_name = django_filters.CharFilter(field_name='warehouse__name', lookup_expr='icontains')
|
||
cancelled = django_filters.BooleanFilter()
|
||
has_offset = django_filters.BooleanFilter(method='filter_has_offset')
|
||
date_from = django_filters.DateFilter(field_name='created_at', lookup_expr='gte')
|
||
date_to = django_filters.DateFilter(field_name='created_at', lookup_expr='lte')
|
||
|
||
def filter_has_offset(self, queryset, name, value):
|
||
"""过滤是否有冲抵记录"""
|
||
if value:
|
||
return queryset.exclude(offset_to__isnull=True)
|
||
else:
|
||
return queryset.filter(offset_to__isnull=True)
|
||
|
||
class Meta:
|
||
model = models.StockSnapshot
|
||
fields = [
|
||
'product', 'warehouse', 'stock_change_record',
|
||
'unit', 'cancelled'
|
||
]
|
||
|
||
|
||
class StockSnapshotListView(ListAPIView):
|
||
"""
|
||
库存快照列表视图(只读)
|
||
|
||
提供库存变动快照的查询功能
|
||
|
||
查询参数:
|
||
- product: 产品ID
|
||
- product_name: 产品名称(模糊查询)
|
||
- product_code: 产品编码(模糊查询)
|
||
- warehouse: 仓库ID
|
||
- warehouse_name: 仓库名称(模糊查询)
|
||
- stock_change_record: 关联的库存变动记录ID
|
||
- unit: 单位
|
||
- cancelled: 是否已取消(true/false)
|
||
- has_offset: 是否有冲抵记录(true/false)
|
||
- date_from: 开始日期(格式:YYYY-MM-DD)
|
||
- date_to: 结束日期(格式:YYYY-MM-DD)
|
||
- search: 全文搜索(产品名称、产品编码、仓库名称)
|
||
- ordering: 排序字段
|
||
"""
|
||
serializer_class = StockSnapshotSerializer
|
||
pagination_class = LimitedLimitOffsetPagination
|
||
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
|
||
filterset_class = StockSnapshotFilterSet
|
||
search_fields = ['product__name', 'product__code', 'warehouse__name']
|
||
ordering_fields = [
|
||
'id', 'delta', 'quantity_before', 'quantity_after',
|
||
'created_at', 'updated_at', 'offset_at', 'cancelled_at'
|
||
]
|
||
ordering = ['-created_at']
|
||
|
||
def get_queryset(self):
|
||
"""优化查询,预加载关联数据"""
|
||
return models.StockSnapshot.objects.select_related(
|
||
'product', 'warehouse', 'stock_change_record'
|
||
).all()
|