Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop
This commit is contained in:
commit
3db99496fe
|
@ -15,7 +15,8 @@ class MbFilterSet(filters.FilterSet):
|
|||
|
||||
def filter_tag(self, queryset, name, value):
|
||||
if value == 'expired':
|
||||
queryset = queryset.exclude(expiration_date=None).filter(expiration_date__lte=timezone.now())
|
||||
queryset = queryset.exclude(expiration_date=None).filter(
|
||||
expiration_date__lte=timezone.now())
|
||||
return queryset
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@ class MaterialBatchSerializer(serializers.ModelSerializer):
|
|||
class IProductListSerializer(serializers.ModelSerializer):
|
||||
material_ = MaterialSimpleSerializer(source='material', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
is_mtested = serializers.BooleanField(source='wproduct.is_mtested', read_only=True)
|
||||
is_mtestok = serializers.BooleanField(source='wproduct.is_mtestok', read_only=True)
|
||||
remark_mtest = serializers.CharField(source='wproduct.remark_mtest', read_only=True)
|
||||
|
||||
|
|
|
@ -1,22 +1,36 @@
|
|||
from django_filters import rest_framework as filters
|
||||
|
||||
from apps.sam.models import Order
|
||||
from django.db.models import F
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
class OrderFilterSet(filters.FilterSet):
|
||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||
create_time_end = filters.DateFilter(field_name="create_time", lookup_expr='lte')
|
||||
material = filters.NumberFilter(method='filter_material')
|
||||
tag = filters.CharFilter(method='filter_tag')
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ['product', 'contract', 'customer', 'create_time_start', 'create_time_end']
|
||||
fields = ['product', 'contract', 'customer', 'create_time_start',
|
||||
'create_time_end', 'tag']
|
||||
|
||||
def filter_material(self, queryset, name, value):
|
||||
"""
|
||||
按物料筛选
|
||||
"""
|
||||
return queryset.filter(plan_order__subplan_plan__progress_subplan__material__id=value).distinct()
|
||||
return queryset.filter(
|
||||
plan_order__subplan_plan__progress_subplan__material__id=value).distinct()
|
||||
|
||||
def filter_tag(self, queryset, name, value):
|
||||
if value == 'near_delivery':
|
||||
day7_after = datetime.now() + timedelta(days=7)
|
||||
queryset = queryset.filter(delivered_count__lt=F('count'),
|
||||
delivery_date__lte = datetime.date(day7_after))
|
||||
elif value == 'out_delivery':
|
||||
queryset = queryset.filter(delivered_count__lt=F('count'),
|
||||
delivery_date__gt = datetime.date(datetime.now()))
|
||||
return queryset
|
||||
|
||||
class ContractFilterSet(filters.FilterSet):
|
||||
create_time_start = filters.DateFilter(field_name="create_time", lookup_expr='gte')
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.9 on 2022-01-24 05:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('sam', '0010_auto_20211208_1408'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='order',
|
||||
name='need_mtest',
|
||||
field=models.BooleanField(default=False, verbose_name='是否需要军检'),
|
||||
),
|
||||
]
|
|
@ -66,6 +66,7 @@ class Order(CommonAModel):
|
|||
planed_count = models.PositiveIntegerField('已排数量', default=0)
|
||||
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
|
||||
delivery_date = models.DateField('交货日期')
|
||||
need_mtest = models.BooleanField('是否需要军检', default=False)
|
||||
class Meta:
|
||||
verbose_name = '订单信息'
|
||||
verbose_name_plural = verbose_name
|
||||
|
|
|
@ -63,7 +63,7 @@ class OrderSimpleSerializer(serializers.ModelSerializer):
|
|||
customer_ = CustomerSimpleSerializer(source='customer', read_only=True)
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = '__all__'
|
||||
fields = ['id', 'number', 'contract_', 'customer_', 'need_mtest']
|
||||
|
||||
class SaleCreateSerializer(serializers.ModelSerializer):
|
||||
iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), many=True)
|
||||
|
|
|
@ -136,13 +136,6 @@ class SaleViewSet(CreateUpdateCustomMixin, ListModelMixin, RetrieveModelMixin, C
|
|||
fifo.inout_date = timezone.now()
|
||||
fifo.create_by = request.user
|
||||
fifo.save()
|
||||
# 出库条目 暂时不校验是否军检
|
||||
# spds = SaleProduct.objects.filter(sale=obj)
|
||||
# for i in spds:
|
||||
# if i.is_mtested and i.is_mtestok:
|
||||
# pass
|
||||
# else:
|
||||
# raise exceptions.APIException('存在未军检产品')
|
||||
# 创建出库条目
|
||||
ips = IProduct.objects.filter(sale_iproduct__sale=obj)
|
||||
items = ips.values('warehouse', 'material', 'batch').annotate(total=Count('id'))
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from django_filters import rest_framework as filters
|
||||
from .models import User
|
||||
from utils.mixins import DynamicFieldsFilterMixin
|
||||
|
||||
|
||||
class UserFilter(filters.FilterSet):
|
||||
class UserFilter(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||
name = filters.CharFilter(field_name='name', lookup_expr='contains')
|
||||
class Meta:
|
||||
model = User
|
||||
fields = {
|
||||
'name': ['exact', 'contains'],
|
||||
'is_active': ['exact'],
|
||||
}
|
||||
fields = ['name', 'is_active']
|
|
@ -5,6 +5,7 @@ from rest_framework import serializers
|
|||
|
||||
from .models import (Dict, DictType, File, Organization, Permission, Position,
|
||||
Role, User)
|
||||
from utils.mixins import DynamicFieldsSerializerMixin
|
||||
|
||||
class IntervalSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
@ -132,7 +133,7 @@ class UserSimpleSerializer(serializers.ModelSerializer):
|
|||
# fields = ['id', 'username', 'name', 'is_active', 'dept_name', 'dept']
|
||||
|
||||
|
||||
class UserListSerializer(serializers.ModelSerializer):
|
||||
class UserListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
用户列表序列化
|
||||
"""
|
||||
|
|
|
@ -2,6 +2,7 @@ from django_filters import rest_framework as filters
|
|||
from apps.mtm.models import Material, Step
|
||||
|
||||
from apps.wpm.services import WpmServies
|
||||
from utils.mixins import DynamicFieldsFilterMixin
|
||||
from .models import Operation, OperationMaterial, OperationRecord, WMaterial, WProduct
|
||||
|
||||
|
||||
|
@ -28,11 +29,15 @@ class WMaterialFilterSet(filters.FilterSet):
|
|||
return queryset
|
||||
|
||||
|
||||
class WProductFilterSet(filters.FilterSet):
|
||||
class WProductFilterSet(DynamicFieldsFilterMixin, filters.FilterSet):
|
||||
tag = filters.CharFilter(method='filter_tag')
|
||||
production_plan = filters.NumberFilter(
|
||||
field_name='subproduction_plan__production_plan')
|
||||
def filter_fields(self, queryset, name, value):
|
||||
return queryset
|
||||
|
||||
def filter_omit(self, queryset, name, value):
|
||||
return queryset
|
||||
class Meta:
|
||||
model = WProduct
|
||||
fields = ['step', 'subproduction_plan', 'material',
|
||||
|
|
|
@ -120,7 +120,6 @@ class WProduct(CommonAModel):
|
|||
on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket')
|
||||
|
||||
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
||||
is_mtested = models.BooleanField('是否军检', default=False)
|
||||
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
||||
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
||||
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
||||
|
@ -194,7 +193,6 @@ class WproductFlow(CommonAModel):
|
|||
ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单',
|
||||
on_delete=models.SET_NULL, null=True, blank=True)
|
||||
to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE)
|
||||
is_mtested = models.BooleanField('是否军检', default=False)
|
||||
is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True)
|
||||
remark_mtest = models.TextField('军检备注', null=True, blank=True)
|
||||
last_test_result = models.BooleanField('最后一次检验结果', null=True, blank=True)
|
||||
|
|
|
@ -20,6 +20,7 @@ from apps.system.serializers import UserSimpleSerializer
|
|||
from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket
|
||||
from django.db import transaction
|
||||
from apps.sam.models import Order
|
||||
from utils.mixins import DynamicFieldsSerializerMixin
|
||||
|
||||
class PickHalfSerializer(serializers.Serializer):
|
||||
id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID')
|
||||
|
@ -147,7 +148,7 @@ class WProductBaseSerializer(serializers.ModelSerializer):
|
|||
model = WProduct
|
||||
fields = '__all__'
|
||||
|
||||
class WProductListSerializer(serializers.ModelSerializer):
|
||||
class WProductListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
半成品列表
|
||||
"""
|
||||
|
@ -157,6 +158,7 @@ class WProductListSerializer(serializers.ModelSerializer):
|
|||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
children = serializers.SerializerMethodField()
|
||||
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
|
||||
order_ = serializers.SerializerMethodField()
|
||||
class Meta:
|
||||
model = WProduct
|
||||
fields = '__all__'
|
||||
|
@ -167,6 +169,11 @@ class WProductListSerializer(serializers.ModelSerializer):
|
|||
return WProductBaseSerializer(instance=wps, many=True).data
|
||||
return []
|
||||
|
||||
def get_order_(self, obj):
|
||||
order = Order.objects.select_related('contract', 'customer').filter(
|
||||
plan_order__subplan_plan__wproduct_subplan=obj).first()
|
||||
return OrderSimpleSerializer(instance=order).data
|
||||
|
||||
class WProductCardBaseSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
产品流程序列化
|
||||
|
@ -224,6 +231,8 @@ class WProductDetailSerializer(serializers.ModelSerializer):
|
|||
subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True)
|
||||
warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True)
|
||||
children = serializers.SerializerMethodField()
|
||||
to_order_ = OrderSimpleSerializer(source='to_order', read_only=True)
|
||||
order_ = OrderSimpleSerializer(source='subproduction_plan__production_plan__order', read_only=True)
|
||||
class Meta:
|
||||
model = WProduct
|
||||
fields = '__all__'
|
||||
|
@ -231,7 +240,6 @@ class WProductDetailSerializer(serializers.ModelSerializer):
|
|||
def get_children(self, obj):
|
||||
wps = WProduct.objects.filter(child=obj)
|
||||
if wps.exists():
|
||||
print(wps)
|
||||
return WProductBaseSerializer(instance=wps, many=True).data
|
||||
return []
|
||||
|
||||
|
|
|
@ -148,7 +148,8 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
"""
|
||||
perms_map = {'*': '*'}
|
||||
queryset = WProduct.objects.select_related('step', 'material',
|
||||
'subproduction_plan', 'warehouse', 'to_order').prefetch_related('wproduct_child')
|
||||
'subproduction_plan', 'warehouse', 'subproduction_plan__production_plan__order',
|
||||
'to_order').prefetch_related('wproduct_child')
|
||||
serializer_class = WProductListSerializer
|
||||
filterset_class = WProductFilterSet
|
||||
search_fields = ['number']
|
||||
|
@ -398,12 +399,11 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
|||
军检
|
||||
"""
|
||||
obj = self.get_object()
|
||||
if obj.is_mtested:
|
||||
if obj.is_mtestok is None:
|
||||
raise exceptions.APIException('已进行军检')
|
||||
if obj.material.type != Material.MA_TYPE_GOOD:
|
||||
raise exceptions.APIException('军检必须是成品')
|
||||
obj.remark_mtest = request.data.get('remark_mtest', None)
|
||||
obj.is_mtested = True
|
||||
is_mtestok = request.data.get('is_mtestok')
|
||||
obj.is_mtestok = is_mtestok
|
||||
if is_mtestok:
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
"""
|
||||
Mixin to dynamically select only a subset of fields per DRF resource.
|
||||
"""
|
||||
# import warnings
|
||||
from django_filters import rest_framework as filters
|
||||
|
||||
# from django.conf import settings
|
||||
class DynamicFieldsFilterMixin(object):
|
||||
fields = filters.CharFilter(method='filter_fields')
|
||||
omit = filters.CharFilter(method='filter_omit')
|
||||
def filter_fields(self, queryset, name, value):
|
||||
return queryset
|
||||
|
||||
def filter_omit(self, queryset, name, value):
|
||||
return queryset
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
fields = super(DynamicFieldsFilterMixin, self).fields
|
||||
fields.extend(['fields', 'omit'])
|
||||
return fields
|
||||
|
||||
class DynamicFieldsSerializerMixin(object):
|
||||
"""
|
||||
A serializer mixin that takes an additional `fields` argument that controls
|
||||
which fields should be displayed.
|
||||
"""
|
||||
|
||||
@property
|
||||
def fields(self):
|
||||
"""
|
||||
Filters the fields according to the `fields` query parameter.
|
||||
A blank `fields` parameter (?fields) will remove all fields. Not
|
||||
passing `fields` will pass all fields individual fields are comma
|
||||
separated (?fields=id,name,url,email).
|
||||
"""
|
||||
fields = super(DynamicFieldsSerializerMixin, self).fields
|
||||
|
||||
if not hasattr(self, '_context'):
|
||||
# We are being called before a request cycle
|
||||
return fields
|
||||
|
||||
# Only filter if this is the root serializer, or if the parent is the
|
||||
# root serializer with many=True
|
||||
is_root = self.root == self
|
||||
parent_is_list_root = self.parent == self.root and getattr(self.parent, 'many', False)
|
||||
if not (is_root or parent_is_list_root):
|
||||
return fields
|
||||
|
||||
try:
|
||||
request = self.context['request']
|
||||
except KeyError:
|
||||
# conf = getattr(settings, 'DRF_DYNAMIC_FIELDS', {})
|
||||
# if not conf.get('SUPPRESS_CONTEXT_WARNING', False) is True:
|
||||
# warnings.warn('Context does not have access to request. '
|
||||
# 'See README for more information.')
|
||||
return fields
|
||||
|
||||
# NOTE: drf test framework builds a request object where the query
|
||||
# parameters are found under the GET attribute.
|
||||
params = getattr(
|
||||
request, 'query_params', getattr(request, 'GET', None)
|
||||
)
|
||||
# if params is None:
|
||||
# warnings.warn('Request object does not contain query paramters')
|
||||
|
||||
try:
|
||||
filter_fields = params.get('fields', None).split(',')
|
||||
except AttributeError:
|
||||
filter_fields = None
|
||||
|
||||
try:
|
||||
omit_fields = params.get('omit', None).split(',')
|
||||
except AttributeError:
|
||||
omit_fields = []
|
||||
|
||||
# Drop any fields that are not specified in the `fields` argument.
|
||||
existing = set(fields.keys())
|
||||
if filter_fields is None:
|
||||
# no fields param given, don't filter.
|
||||
allowed = existing
|
||||
else:
|
||||
allowed = set(filter(None, filter_fields))
|
||||
|
||||
# omit fields in the `omit` argument.
|
||||
omitted = set(filter(None, omit_fields))
|
||||
|
||||
for field in existing:
|
||||
|
||||
if field not in allowed:
|
||||
fields.pop(field, None)
|
||||
|
||||
if field in omitted:
|
||||
fields.pop(field, None)
|
||||
|
||||
return fields
|
Loading…
Reference in New Issue