Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shijing 2022-01-25 08:48:13 +08:00
commit 3db99496fe
14 changed files with 160 additions and 27 deletions

View File

@ -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

View File

@ -51,10 +51,9 @@ 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)
class Meta:
model = IProduct
fields = '__all__'

View File

@ -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')

View File

@ -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='是否需要军检'),
),
]

View File

@ -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

View File

@ -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)

View File

@ -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'))

View File

@ -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']

View File

@ -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):
"""
用户列表序列化
"""

View File

@ -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',

View File

@ -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)

View File

@ -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__'
@ -166,6 +168,11 @@ class WProductListSerializer(serializers.ModelSerializer):
if wps.exists():
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 []

View File

@ -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:

96
hb_server/utils/mixins.py Normal file
View File

@ -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