factory/apps/inm/serializers.py

386 lines
16 KiB
Python

from rest_framework import serializers
from rest_framework.exceptions import ValidationError, ParseError
from apps.mtm.serializers import MaterialSerializer
from apps.pum.models import PuOrder
from apps.sam.models import Order
from apps.system.models import Dept, User
from apps.utils.constants import EXCLUDE_FIELDS_BASE, EXCLUDE_FIELDS_DEPT, EXCLUDE_FIELDS
from apps.utils.serializers import CustomModelSerializer
from apps.mtm.models import Material
from .models import MIO, MaterialBatch, MIOItem, WareHouse, MIOItemA, MaterialBatchA, MIOItemw
from django.db import transaction
from server.settings import get_sysconfig
from apps.wpmw.models import Wpr
class WareHourseSerializer(CustomModelSerializer):
class Meta:
model = WareHouse
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS_DEPT
class MaterialBatchAListSerializer(CustomModelSerializer):
material_ = MaterialSerializer(source='material', read_only=True)
class Meta:
model = MaterialBatchA
fields = ['material', 'batch', 'rate', 'mb', 'id', 'material_']
class MaterialBatchSerializer(CustomModelSerializer):
warehouse_name = serializers.CharField(
source='warehouse.name', read_only=True)
material_name = serializers.StringRelatedField(
source='material', read_only=True)
supplier_name = serializers.StringRelatedField(
source='supplier', read_only=True)
material_ = MaterialSerializer(source='material', read_only=True)
defect_name = serializers.CharField(source="defect.name", read_only=True)
class Meta:
model = MaterialBatch
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS_BASE
class MaterialBatchDetailSerializer(CustomModelSerializer):
warehouse_name = serializers.CharField(
source='warehouse.name', read_only=True)
material_name = serializers.CharField(
source='material.name', read_only=True)
material_ = MaterialSerializer(source='material', read_only=True)
assemb = MaterialBatchAListSerializer(
source='a_mb', read_only=True, many=True)
supplier_name = serializers.StringRelatedField(
source='supplier', read_only=True)
class Meta:
model = MaterialBatch
fields = '__all__'
class MIOListSerializer(CustomModelSerializer):
create_by_name = serializers.CharField(
source='create_by.name', read_only=True)
submit_user_name = serializers.CharField(
source='submit_user.name', read_only=True)
do_user_name = serializers.CharField(
source='do_user.name', read_only=True)
mio_user_name = serializers.CharField(
source='mio_user.name', read_only=True)
belong_dept_name = serializers.CharField(
source='belong_dept.name', read_only=True)
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
supplier_name = serializers.CharField(
source='supplier.name', read_only=True)
customer_name = serializers.CharField(
source='customer.name', read_only=True)
order_number = serializers.CharField(source='order.number', read_only=True)
pu_order_number = serializers.CharField(
source='pu_order.number', read_only=True)
class Meta:
model = MIO
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + \
['state', 'submit_time', 'submit_user', 'number']
class MIOItemACreateSerializer(CustomModelSerializer):
class Meta:
model = MIOItemA
fields = ['material', 'batch', 'zhuidu',
'b_zuidawaijing', 'g_zuidaneijing']
class MIOItemwSerializer(CustomModelSerializer):
class Meta:
model = MIOItemw
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE + ["mioitem"]
class MIOItemCreateSerializer(CustomModelSerializer):
assemb = MIOItemACreateSerializer(
label='组合件信息', many=True, write_only=True, required=False)
mioitemw = MIOItemwSerializer(many=True, required=False)
class Meta:
model = MIOItem
fields = ['mio', 'warehouse', 'material',
'batch', 'count', 'assemb', 'is_testok', 'mioitemw', 'mb', 'wm']
extra_kwargs = {
'mio': {'required': True}, 'warehouse': {'required': False},
'material': {'required': False}, 'batch': {'required': False}}
def create(self, validated_data):
mio:MIO = validated_data['mio']
mb = validated_data.get('mb', None)
wm = validated_data.get('wm', None)
if mio.type == MIO.MIO_TYPE_DO_IN:
if not wm:
raise ParseError('生产入库必须指定车间库存')
elif mio.type == MIO.MIO_TYPE_DO_OUT:
if not mb:
raise ParseError('生产领料必须指定仓库库存')
if mb:
validated_data["material"] = mb.material
validated_data["batch"] = mb.batch
validated_data["warehouse"] = mb.warehouse
elif wm:
validated_data["material"] = wm.material
validated_data["batch"] = wm.batch
material: Material = validated_data['material']
batch = validated_data['batch']
if material.is_hidden:
raise ParseError('隐式物料不可出入库')
if mio.state != MIO.MIO_CREATE:
raise ParseError('出入库记录非创建中不可新增')
# 生产领料要校验是否进行检验
# 某些客户此处无需校验
check_test_when_do_out = get_sysconfig('mes.check_test_when_do_out', True)
if check_test_when_do_out and mio.type == MIO.MIO_TYPE_DO_OUT:
mis = MIOItem.objects.filter(batch=batch, material=material, mio__type__in=[MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_OTHER_IN])
if mis.exists() and (not mis.exclude(test_date=None).exists()):
raise ParseError('该批次的物料未经检验')
with transaction.atomic():
count = validated_data["count"]
batch = validated_data["batch"]
assemb = validated_data.pop('assemb', [])
mioitemw = validated_data.pop('mioitemw', [])
instance = super().create(validated_data)
assemb_dict = {}
for i in assemb:
assemb_dict[i['material'].id] = i
if material.is_assemb and '_in' in mio.type: # 仅入库且是组合件的时候需要填写下一级
components = material.components
for k, v in components.items():
if k in assemb_dict:
mia = assemb_dict[k]
MIOItemA.objects.create(
mioitem=instance, rate=v, **mia)
else:
raise ParseError('缺少组合件')
if material.tracking == Material.MA_TRACKING_SINGLE:
if len(mioitemw) == 0:
if mb:
wpr_qs = Wpr.get_qs_by_mb(mb)
if wpr_qs.count() == validated_data["count"]:
for item in wpr_qs:
MIOItemw.objects.create(mioitem=instance, number=item.number, wpr=item)
else:
raise ParseError('请提供产品明细编号')
elif wm:
wpr_qs = Wpr.get_qs_by_wm(wm)
if wpr_qs.count() == validated_data["count"]:
for item in wpr_qs:
MIOItemw.objects.create(mioitem=instance, number=item.number, wpr=item)
else:
raise ParseError('请提供产品明细编号')
elif mio.type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_OTHER_IN] and count==1:
MIOItemw.objects.create(mioitem=instance, number=batch)
else:
raise ParseError('不支持自动生成请提供产品明细')
elif len(mioitemw) >= 1:
mio_type = mio.type
for item in mioitemw:
if item.get("wpr", None) is None and mio_type != "pur_in":
raise ParseError(f'{item["number"]}_请提供产品明细ID')
else:
MIOItemw.objects.create(mioitem=instance, **item)
return instance
class MIOItemAListSerializer(CustomModelSerializer):
material_ = MaterialSerializer(source='material', read_only=True)
material_name = serializers.StringRelatedField(
source='material', read_only=True)
class Meta:
model = MIOItemA
fields = ['material', 'batch', 'rate', 'mioitem',
'id', 'material_', 'material_name']
class MIOItemSerializer(CustomModelSerializer):
warehouse_name = serializers.CharField(
source='warehouse.name', read_only=True)
material_ = MaterialSerializer(source='material', read_only=True)
assemb = MIOItemAListSerializer(
source='a_mioitem', read_only=True, many=True)
material_name = serializers.StringRelatedField(
source='material', read_only=True)
inout_date = serializers.DateField(source='mio.inout_date', read_only=True)
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
mioitemw = MIOItemwSerializer(many=True, required=False)
class Meta:
model = MIOItem
fields = '__all__'
class MIODoSerializer(CustomModelSerializer):
belong_dept = serializers.PrimaryKeyRelatedField(
label="车间", queryset=Dept.objects.all(), required=False)
do_user = serializers.PrimaryKeyRelatedField(
label="执行人", queryset=User.objects.all(), required=True)
note = serializers.CharField(
required=False, allow_blank=True)
class Meta:
model = MIO
fields = ['id', 'number', 'note', 'do_user',
'belong_dept', 'type', 'inout_date', 'mgroup', 'mio_user']
extra_kwargs = {'inout_date': {'required': True}, 'do_user': {'required': True}, 'number': {"required": False, "allow_blank": True}}
def validate(self, attrs):
if 'mgroup' in attrs and attrs['mgroup']:
attrs['belong_dept'] = attrs['mgroup'].belong_dept
if not attrs.get("belong_dept", None):
raise ParseError('请选择车间或工段')
return attrs
def create(self, validated_data):
if not validated_data.get("number", None):
validated_data["number"] = MIO.get_a_number(validated_data["type"])
if validated_data['type'] not in [MIO.MIO_TYPE_DO_OUT, MIO.MIO_TYPE_DO_IN]:
raise ValidationError('出入库类型错误')
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('type', None)
return super().update(instance, validated_data)
class MIOSaleSerializer(CustomModelSerializer):
# order = serializers.PrimaryKeyRelatedField(
# label="订单", queryset=Order.objects.all(), required=True)
note = serializers.CharField(
required=False, allow_blank=True)
class Meta:
model = MIO
fields = ['id', 'number', 'note', 'order', 'inout_date', 'customer', 'mio_user']
extra_kwargs = {'inout_date': {'required': True}, 'number': {"required": False, "allow_blank": True}}
def create(self, validated_data):
validated_data['type'] = MIO.MIO_TYPE_SALE_OUT
order: Order = validated_data.get('order', None)
if not validated_data.get("number", None):
validated_data["number"] = MIO.get_a_number(validated_data["type"])
if order:
if order.state in [Order.ORDER_CREATE, Order.ORDER_DELIVERED]:
raise ValidationError('销售订单状态错误')
validated_data['customer'] = order.customer
if order.belong_dept:
validated_data['belong_dept'] = order.belong_dept
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('type', None)
return super().update(instance, validated_data)
class MIOPurSerializer(CustomModelSerializer):
# pu_order = serializers.PrimaryKeyRelatedField(
# label="采购订单", queryset=PuOrder.objects.all(), required=True)
note = serializers.CharField(
required=False, allow_blank=True)
class Meta:
model = MIO
fields = ['id', 'number', 'note', 'pu_order', 'inout_date', 'supplier', 'mio_user']
extra_kwargs = {'inout_date': {'required': True}, 'number': {"required": False, "allow_blank": True}}
def create(self, validated_data):
validated_data['type'] = MIO.MIO_TYPE_PUR_IN
if not validated_data.get("number", None):
validated_data["number"] = MIO.get_a_number(validated_data["type"])
pu_order: PuOrder = validated_data.get('pu_order', None)
if pu_order:
if pu_order.state in [PuOrder.PUORDER_CREATE, PuOrder.PUORDER_DONE]:
raise ValidationError('采购订单状态错误')
validated_data['supplier'] = pu_order.supplier
if pu_order.belong_dept:
validated_data['belong_dept'] = pu_order.belong_dept
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('type', None)
return super().update(instance, validated_data)
class MIOOtherSerializer(CustomModelSerializer):
note = serializers.CharField(
required=False, allow_blank=True)
class Meta:
model = MIO
fields = ['id', 'number', 'note', 'supplier',
'customer', 'type', 'inout_date', 'mio_user']
extra_kwargs = {'inout_date': {'required': True}, 'number': {"required": False, "allow_blank": True}}
def create(self, validated_data):
if not validated_data.get("number", None):
validated_data["number"] = MIO.get_a_number(validated_data["type"])
if validated_data['type'] not in [MIO.MIO_TYPE_OTHER_OUT, MIO.MIO_TYPE_OTHER_IN]:
raise ValidationError('出入库类型错误')
return super().create(validated_data)
def update(self, instance, validated_data):
validated_data.pop('type', None)
return super().update(instance, validated_data)
class MIODetailSerializer(MIOListSerializer):
items = MIOItemSerializer(source='item_mio', many=True, read_only=True)
class MIOItemTestSerializer(CustomModelSerializer):
class Meta:
model = MIOItem
fields = ['id', 'test_date', 'test_user', 'count_notok', 'count_n_zw', 'count_n_tw',
'count_n_qp', 'count_n_wq', 'count_n_dl', 'count_n_pb', 'count_n_dxt', 'count_n_js', 'count_n_qx', 'count_n_zz', 'count_n_ysq', 'count_n_qt', 'count_n_hs', 'count_n_b', 'test_note']
extra_kwargs = {
'test_date': {'required': True},
'test_user': {'required': True}
}
def validate(self, attrs):
count_notok = 0
for i in attrs:
if 'count_n_' in i:
count_notok = count_notok + attrs[i]
attrs['count_notok'] = count_notok
return attrs
class MioItemAnaSerializer(serializers.Serializer):
start_date = serializers.DateField(label='开始日期', required=True)
end_date = serializers.DateField(label='结束日期', required=True)
material_cate = serializers.CharField(label='物料系列', required=True)
class MIOItemPurInTestSerializer(CustomModelSerializer):
class Meta:
model = MIOItem
fields = ['id', 'test_date', 'test_user',
'count_bag', 'count_sampling', 'weight_kgs', 'is_testok', 'test_note']
extra_kwargs = {
'test_date': {'required': True},
'test_user': {'required': True}
}
def validate(self, attrs):
if 'count_sampling' in attrs and attrs['count_sampling']:
pass
else:
weight_kgs = attrs['weight_kgs']
attrs['weight_kgs'] = [float(i) for i in weight_kgs]
attrs['count_sampling'] = len(attrs['weight_kgs'])
return super().validate(attrs)