factory/apps/wpm/serializers.py

1285 lines
58 KiB
Python

from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from apps.utils.serializers import CustomModelSerializer
from rest_framework import serializers
from rest_framework.exceptions import ParseError
from datetime import datetime
from .models import (SfLog, StLog, SfLogExp, WMaterial, Mlog,
Handover, Handoverb, Mlogb, AttLog,
OtherLog, Fmlog, BatchSt, Mlogbw, Handoverbw, MlogbDefect, MlogUser, BatchLog)
from apps.system.models import Dept, User
from apps.system.serializers import UserSimpleSerializer
from apps.pm.models import Mtask, Mtaskb
from apps.wpm.tasks import cal_enstat_when_pcoal_heat_change, cal_enstat_when_team_change, cal_exp_duration_sec
from apps.wpm.services import get_sflog, find_material_can_change, generate_new_batch
from apps.mtm.models import Mgroup, TeamMember, Shift, Material, Route, Process
from apps.mtm.serializers import MaterialSimpleSerializer
from django.db import transaction
from django.utils import timezone
from django.core.cache import cache
from django.utils.timezone import localdate
from apps.qm.models import NotOkOption, Qct
from apps.wf.serializers import TicketSimpleSerializer
from apps.wpmw.models import Wpr
from apps.qm.serializers import FtestProcessSerializer
import logging
from apps.qm.models import Defect
from apps.utils.snowflake import idWorker
from decimal import Decimal
mylogger = logging.getLogger("log")
class OtherLogSerializer(CustomModelSerializer):
class Meta:
model = OtherLog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS
class StLogSerializer(CustomModelSerializer):
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
current_sflog = serializers.CharField(label='当前处理值班', write_only=True)
current_note = serializers.CharField(
label='值班处理备注', write_only=True, allow_blank=True)
class Meta:
model = StLog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + \
['is_shutdown', 'sflog', 'duration']
def create(self, validated_data):
current_sflog_id = validated_data.pop('current_sflog')
current_note = validated_data.pop('current_note', '')
with transaction.atomic():
sflog = get_sflog(
validated_data['mgroup'], validated_data['start_time'])
if current_sflog_id != sflog.id:
raise ParseError('值班时间与发生时间不一致')
instance = super().create(validated_data)
instance.sflog = sflog
instance.save()
SfLogExp.objects.create(
sflog=sflog, stlog=instance, create_by=self.context['request'].user, note=current_note)
return instance
def update(self, instance, validated_data):
if instance.is_shutdown: # 停机不可编辑end_time
validated_data.pop('end_time', None)
# if instance.end_time:
# raise ParseError('该异常已结束无需编辑')
with transaction.atomic():
validated_data.pop('mgroup', None)
validated_data.pop('start_time', None)
end_time = validated_data.pop('end_time', None)
current_sflog = validated_data.pop('current_sflog')
current_note = validated_data.pop('current_note', '')
instance = super().update(instance, validated_data)
if end_time: # 需要把涉及到的sflog都拉入
cal_exp_duration_sec(instance.id)
try:
sflogexp = SfLogExp.objects.get(
stlog=instance, sflog=current_sflog)
sflogexp.note = current_note
sflogexp.save()
except SfLogExp.DoesNotExist:
raise ParseError('该异常无需本班填写')
return instance
def validate(self, attrs):
now = timezone.now()
start_time: datetime = attrs['start_time']
end_time: datetime = attrs.get('end_time', None)
if start_time > now:
raise ParseError('开始时间应为历史时间')
if end_time:
if end_time > now:
raise ParseError('开始时间应为历史时间')
if end_time > start_time:
attrs['duration_sec'] = (
end_time - start_time).total_seconds()
else:
raise ParseError('结束时间应大于开始时间')
return super().validate(attrs)
class SfLogSerializer(CustomModelSerializer):
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
team_name = serializers.CharField(source='team.name', read_only=True)
shift_name = serializers.CharField(source='shift.name', read_only=True)
leader_name = serializers.CharField(source='leader.name', read_only=True)
class Meta:
model = SfLog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + \
['mgroup', 'start_time', 'end_time', 'belong_dept']
extra_kwargs = {
'team': {'required': True},
'leader': {'required': True}
}
def update(self, instance, validated_data):
old_pcoal_heat = instance.pcoal_heat
old_team = instance.team
instance: SfLog = super().update(instance, validated_data)
new_pcoal_heat = instance.pcoal_heat
new_team = instance.team
mgroup: Mgroup = instance.mgroup
# 更新煤粉热值触发计算
if instance.mgroup.name == '回转窑' and instance.shift.name in ['早班', '白班']:
mylogger.info(f'回转窑白班/早班{instance.get_ymd}更新{new_pcoal_heat}-{old_pcoal_heat}')
year_s, month_s, day_s = instance.get_ymd
if new_pcoal_heat: # 更新一下缓存
cache.set(f'pcoal_heat_{year_s}_{month_s}_{day_s}', new_pcoal_heat, timeout=60 * 60 * 48)
if new_pcoal_heat != old_pcoal_heat:
cal_enstat_when_pcoal_heat_change.delay(year_s, month_s, day_s)
# 更新班组触发计算
if new_team != old_team:
default_state = 'pending'
if timezone.now() > instance.end_time:
default_state = 'normal'
# 分配班组时创建人员到岗情况
for item in TeamMember.objects.filter(team=new_team, mgroup=instance.mgroup):
AttLog.objects.get_or_create(sflog=instance, user=item.user, defaults={
'sflog': instance, 'user': item.user, 'post': item.post, 'state': default_state, 'create_by': self.context['request'].user})
if mgroup.need_enm:
from apps.qm.tasks import cal_quastat_sflog
cal_enstat_when_team_change.delay(instance.id)
cal_quastat_sflog.delay(instance.id)
return instance
def to_representation(self, instance):
ret = super().to_representation(instance)
if "shut_sec" in ret:
ret["shut_hour"] = "{:.2f}".format(round(ret['shut_sec']/3600, 2))
return ret
# def to_internal_value(self, data):
# if hasattr(self.Meta, 'update_fields') and self.context['request'].method in ['PUT', 'PATCH']:
# u_fields = self.Meta.update_fields
# new_data = {key: data[key] for key in u_fields if key in data}
# return super().to_internal_value(new_data)
# return super().to_internal_value(data)
class SflogExpSerializer(CustomModelSerializer):
# mgroup = serializers.CharField(source='sflog.mgroup.id', read_only=True)
# mgroup_name = serializers.CharField(
# source='sflog.mgroup.name', read_only=True)
# stlog_ = StLogSerializer(source='stlog', read_only=True)
# happen_time = serializers.DateTimeField(required=True, label='发生时间')
# cate = serializers.CharField(required=True, label='原因类别')
sflog_ = SfLogSerializer(source='sflog', read_only=True)
stlog_ = StLogSerializer(source='stlog', read_only=True)
class Meta:
model = SfLogExp
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + ['sflog', 'stlog', 'duration']
class WMaterialSerializer(CustomModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
supplier_name = serializers.CharField(source='supplier.name', read_only=True)
material_name = serializers.StringRelatedField(
source='material', read_only=True)
mgroup_name = serializers.StringRelatedField(source='mgroup.name', read_only=True)
belong_dept_name = serializers.CharField(
source='belong_dept.name', read_only=True)
material_ofrom_name = serializers.StringRelatedField(source='material_ofrom', read_only=True)
material_origin_name = serializers.StringRelatedField(source='material_origin', read_only=True)
notok_sign_name = serializers.SerializerMethodField()
defect_name = serializers.CharField(source="defect.name", read_only=True)
count_working = serializers.IntegerField(read_only=True, label='在制数量')
def get_notok_sign_name(self, obj):
return getattr(NotOkOption, obj.notok_sign, NotOkOption.qt).label if obj.notok_sign else None
class Meta:
model = WMaterial
fields = '__all__'
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['count_cando'] = str(Decimal(ret['count']) - Decimal(ret['count_working']))
return ret
class MlogbDefectSerializer(CustomModelSerializer):
defect_name = serializers.CharField(source="defect.name", read_only=True)
defect_okcate = serializers.CharField(source="defect.okcate", read_only=True)
class Meta:
model = MlogbDefect
fields = ["id", "defect_name", "count", "mlogb", "defect", "defect_okcate"]
read_only_fields = EXCLUDE_FIELDS_BASE + ["mlogb"]
def validate(self, attrs):
if attrs["count"] < 0:
raise serializers.ValidationError("存在负数!")
return attrs
class MlogbSerializer(CustomModelSerializer):
material_out_ = MaterialSimpleSerializer(
source='material_out', read_only=True)
material_out_name = serializers.StringRelatedField(
source='material_out', read_only=True)
class Meta:
model = Mlogb
fields = ['id', 'material_out', 'count_ok',
'material_out_', 'material_out_name', "mlog"]
extra_kwargs = {
'material_out': {'required': True, 'allow_null': False}}
read_only_fields = EXCLUDE_FIELDS_BASE + ["mlog"]
class MlogListSerializer(CustomModelSerializer):
mstate_json = serializers.JSONField(source='mgroup.process.mstate_json', read_only=True)
supplier_name = serializers.CharField(source='supplier.name', read_only=True)
# routepack_name = serializers.CharField(source='route.routepack.name', read_only=True)
belong_dept = serializers.CharField(
source='mgroup.belong_dept.id', read_only=True)
belong_dept_name = serializers.CharField(
source='mgroup.belong_dept.name', read_only=True)
mgroup_name = serializers.CharField(
source='mgroup.name', read_only=True)
mtask_count = serializers.IntegerField(
source='mtask.count', read_only=True)
create_by_name = serializers.CharField(
source='create_by.name', read_only=True)
update_by_name = serializers.CharField(
source='update_by.name', read_only=True)
material_in_ = MaterialSimpleSerializer(
source='material_in', read_only=True)
material_out_ = MaterialSimpleSerializer(
source='material_out', read_only=True)
material_out_name = serializers.StringRelatedField(
source='material_out', read_only=True)
material_in_name = serializers.StringRelatedField(
source='material_in', read_only=True)
handle_user_name = serializers.CharField(
source='handle_user.name', read_only=True)
handle_user_2_name = serializers.CharField(
source='handle_user_2.name', read_only=True)
handle_leader_name = serializers.CharField(
source='handle_leader.name', read_only=True)
equipment_name = serializers.StringRelatedField(
source='equipment', read_only=True)
equipment_2_name = serializers.StringRelatedField(
source='equipment_2', read_only=True)
shift_name = serializers.CharField(source='shift.name', read_only=True)
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
handle_users_ = UserSimpleSerializer(
source='handle_users', many=True, read_only=True)
class Meta:
model = Mlog
fields = '__all__'
class MlogbDetailSerializer(CustomModelSerializer):
material_out_name = serializers.StringRelatedField(
source='material_out', read_only=True)
material_in_name = serializers.StringRelatedField(source='material_in', read_only=True)
material_out_tracking = serializers.IntegerField(source="material_out.tracking", read_only=True)
mlogbdefect = MlogbDefectSerializer(many=True, read_only=True)
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
class Meta:
model = Mlogb
fields = '__all__'
class MlogSerializer(CustomModelSerializer):
mstate_json = serializers.JSONField(source='mgroup.process.mstate_json', read_only=True)
supplier_name = serializers.CharField(source='supplier.name', read_only=True)
# routepack_name = serializers.CharField(source='route.routepack.name', read_only=True)
belong_dept = serializers.CharField(
source='mgroup.belong_dept.id', read_only=True)
belong_dept_name = serializers.CharField(
source='mgroup.belong_dept.name', read_only=True)
mgroup_name = serializers.CharField(
source='mgroup.name', read_only=True)
mtask_count = serializers.IntegerField(
source='mtask.count', read_only=True)
create_by_name = serializers.CharField(
source='create_by.name', read_only=True)
update_by_name = serializers.CharField(
source='update_by.name', read_only=True)
material_in_ = MaterialSimpleSerializer(
source='material_in', read_only=True)
material_out_ = MaterialSimpleSerializer(
source='material_out', read_only=True)
material_out_name = serializers.StringRelatedField(
source='material_out', read_only=True)
material_in_name = serializers.StringRelatedField(
source='material_in', read_only=True)
handle_user_name = serializers.CharField(
source='handle_user.name', read_only=True)
handle_user_2_name = serializers.CharField(
source='handle_user_2.name', read_only=True)
handle_leader_name = serializers.CharField(
source='handle_leader.name', read_only=True)
equipment_name = serializers.StringRelatedField(
source='equipment', read_only=True)
equipment_2_name = serializers.StringRelatedField(
source='equipment_2', read_only=True)
shift_name = serializers.CharField(source='shift.name', read_only=True)
mlogb = MlogbSerializer(
label='多产出件信息', many=True, required=False)
mlogb_full = MlogbDetailSerializer(
label='物料信息', many=True, read_only=True)
handle_users_ = UserSimpleSerializer(
source='handle_users', many=True, read_only=True)
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
mlogdefect = MlogbDefectSerializer(many=True, required=False)
mlogindefect = MlogbDefectSerializer(many=True, label="前道不良", required=False)
class Meta:
model = Mlog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + \
['submit_time', 'submit_user', 'material_outs']
extra_kwargs = {
"batch": {"required": True},
"shift": {"required": True},
"material_out": {"required": True}
}
def create(self, validated_data):
material_out = validated_data['material_out']
mtask:Mtask = validated_data.get('mtask', None)
mlogdefect = validated_data.pop('mlogdefect', None)
mlogbindefect = validated_data.pop('mlogindefect', None)
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
raise ParseError('该任务非下达中不可选择')
with transaction.atomic():
mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().create(validated_data)
# 自动生成mlogb
batch_in = instance.batch
wm_in = instance.wm_in
if wm_in:
batch_in = wm_in.batch
instance.batch = batch_in
instance.save(update_fields=['batch'])
mlogbin = None
if instance.material_in: # 如果有消耗
add_dict = {
'mlog': instance, 'batch': batch_in, 'wm_in': wm_in,
'mtask': instance.mtask, 'material_in': instance.material_in,
'count_use': instance.count_use, 'count_break': instance.count_break,
'count_pn_jgqbl': instance.count_pn_jgqbl
}
if wm_in:
add_dict['batch_ofrom'] = wm_in.batch_ofrom
add_dict['material_ofrom'] = wm_in.material_ofrom
mlogbin = Mlogb.objects.create(**add_dict)
if mlogbindefect is not None:
mlogbin_defect_objects = [
MlogbDefect(**{**item, "mlogb": mlogbin, "id": idWorker.get_id()})
for item in mlogbindefect if item["count"] > 0
]
if mlogbin_defect_objects:
MlogbDefect.objects.bulk_create(mlogbin_defect_objects)
mlogbin.cal_count_pn_jgqbl()
# mlogb只用于组合件输出物填写
brotherId_should_list = material_out.brothers
if brotherId_should_list:
if mlogb:
for item in mlogb:
if item['material_out'].id in brotherId_should_list:
mlogbx = Mlogb.objects.create(
mlog=instance,
batch=instance.batch,
mtask=instance.mtask,
material_out=item['material_out'],
count_ok=item['count_ok'])
if wm_in:
mlogbx.batch_ofrom = wm_in.batch_ofrom
mlogbx.material_ofrom = wm_in.material_ofrom
mlogbx.save(update_fields=["batch_ofrom", "material_ofrom"])
else:
raise ParseError('缺少产出物信息')
else:
# 生成产出物
batch_out = validated_data.get('batch', None)
if batch_out:
pass
else:
batch_out = generate_new_batch(batch_in, instance)
add_dict_2 = {
'mlog': instance, 'batch': batch_out,
'mtask': instance.mtask, 'material_out': instance.material_out,
'count_real': instance.count_real,
'count_ok': instance.count_ok, 'count_notok': instance.count_notok,
'count_break_t': instance.count_break_t,
'qct': instance.qct
}
need_mdfect = False
if mlogdefect is not None:
need_mdfect = True
else:
for f in Mlogb._meta.fields:
if 'count_n_' in f.name:
add_dict_2[f.name] = getattr(instance, f.name)
ddict = {}
if wm_in:
ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}
if mlogbin:
ddict["mlogb_from"] = mlogbin
mlogb, _ = Mlogb.objects.get_or_create(**add_dict_2, defaults=ddict)
if need_mdfect:
mlogb_defect_objects = [
MlogbDefect(**{**item, "mlogb": mlogb, "id": idWorker.get_id()})
for item in mlogdefect if item["count"] > 0
]
if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
mlogb.cal_count_notok()
return instance
def update(self, instance, validated_data):
if instance.fill_way == Mlog.MLOG_23:
raise ParseError('不支持的填写类型')
validated_data.pop('mtask', None)
validated_data.pop('mgroup', None)
mlogdefect = validated_data.pop('mlogdefect', None)
mlogbindefect = validated_data.pop('mlogindefect', None)
if instance.mtask:
validated_data.pop('handle_date', None)
# validated_data.pop('handle_user', None)
with transaction.atomic():
mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().update(instance, validated_data)
wm_in = instance.wm_in
batch_in = instance.batch
if wm_in:
batch_in = wm_in.batch
# 修改消耗
if instance.fill_way in [Mlog.MLOG_12, Mlog.MLOG_2]:
# 自动生成mlogb
if instance.material_in: # 有消耗的情况
minx, _ = Mlogb.objects.get_or_create(
mlog=instance,
batch=batch_in,
wm_in=instance.wm_in,
mtask=instance.mtask,
material_in=instance.material_in
)
if wm_in:
minx.batch_ofrom = wm_in.batch_ofrom
minx.material_ofrom = wm_in.material_ofrom
minx.count_use = instance.count_use
minx.count_break = instance.count_break
minx.count_pn_jgqbl = instance.count_pn_jgqbl
minx.qct = instance.qct
minx.save()
Mlogb.objects.filter(mlog=instance, material_in__isnull=False).exclude(id=minx.id).delete()
if mlogbindefect is not None:
mlogbin_defect_objects = [
MlogbDefect(**{**item, "mlogb": minx, "id": idWorker.get_id()})
for item in mlogbindefect if item["count"] > 0
]
if mlogbin_defect_objects:
MlogbDefect.objects.bulk_create(mlogbin_defect_objects)
minx.cal_count_pn_jgqbl()
# 修改产出
if instance.fill_way == Mlog.MLOG_2 and instance.material_out.brothers:
# 针对兄弟件的情况
Mlogb.objects.filter(mlog=instance, material_out__isnull=False).update(
batch=instance.batch, # 注意mlog的batch有可能会进行修改
count_ok=0)
for item in mlogb:
Mlogb.objects.filter(mlog=instance, material_out=item['material_out']).update(
batch=instance.batch,
count_ok=item['count_ok'])
elif instance.fill_way in [Mlog.MLOG_12, Mlog.MLOG_2]:
# 生成产出物
batch_out = instance.batch
if batch_out:
pass
else:
batch_out = generate_new_batch(batch_in, instance)
mox, _ = Mlogb.objects.get_or_create(mlog=instance, batch=batch_out,
mtask=instance.mtask, material_out=instance.material_out)
mox.count_ok = instance.count_ok
mox.count_notok = instance.count_notok
mox.count_break_t = instance.count_break_t
if wm_in:
mox.batch_ofrom = wm_in.batch
mox.material_ofrom = wm_in.material_ofrom
need_mdefect=False
if mlogdefect is not None:
need_mdefect = True
else:
for f in Mlogb._meta.fields:
if 'count_n_' in f.name:
setattr(mox, f.name, getattr(instance, f.name))
mox.save()
Mlogb.objects.filter(mlog=instance, material_out__isnull=False).exclude(id=mox.id).delete()
if need_mdefect:
MlogbDefect.objects.filter(mlogb__mlog=instance).delete()
mlogb_defect_objects = [
MlogbDefect(**{**item, "mlogb": mox, "id": idWorker.get_id()})
for item in mlogdefect if item["count"] > 0
]
if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
mox.cal_count_notok()
return instance
def validate(self, attrs):
attrs['fill_way'] = Mlog.MLOG_2 # 只填第二级
attrs['mtype'] = Mlog.MTYPE_SELF # 默认为自生产
fmlog:Fmlog = attrs.get('fmlog', None)
mtaskb = attrs.get('mtaskb', None)
if fmlog:
attrs['fill_way'] = Mlog.MLOG_12
wm_in: WMaterial = attrs.get('wm_in', None)
if wm_in:
pass
else:
raise ParseError('未提供消耗的车间物料')
attrs['mgroup'] = fmlog.mgroup
attrs['mtask'] = fmlog.mtask
attrs['route'] = fmlog.route
attrs['mtype'] = fmlog.mgroup.mtype
if attrs['mtask'] and attrs['mtask'].route:
attrs['route'] = attrs['mtask'].route
# if attrs['mtask'].mtaskb and mtaskb is None:
# raise ParseError('子任务不能为空')
if mtaskb and mtaskb.mtask != fmlog.mtask:
raise ParseError('子任务不一致')
if wm_in.state in [WMaterial.WM_OK]:
pass
else:
raise ParseError('非合格品不可使用')
if wm_in.material != attrs['route'].material_in:
raise ParseError('消耗物料与工艺步骤不一致')
if attrs['mtype'] == Mlog.MTYPE_OUT:
supplier = attrs.get('supplier', None)
if not supplier:
raise ParseError('外协必须选择外协单位')
mtask = attrs.get('mtask', None)
count_notok = 0
for i in attrs:
if 'count_n_' in i:
if attrs[i] < 0:
raise ParseError(f'{attrs[i]}不能小于0')
count_notok = count_notok + attrs[i]
attrs['count_notok'] = count_notok
if attrs['count_ok'] < 0:
raise ParseError('合格数量不能小于0')
if attrs['count_real'] >= attrs['count_ok'] + attrs['count_notok']:
pass
else:
raise ParseError('生产数量不能小于合格数量')
if mtask:
if mtask.start_date == mtask.end_date:
attrs['handle_date'] = mtask.start_date
else:
if attrs.get('work_end_time', None):
attrs['handle_date'] = localdate(attrs['work_end_time'])
elif attrs.get('work_start_time', None):
attrs['handle_date'] = localdate(attrs['work_start_time'])
mtaskb: Mtaskb = attrs.get('mtaskb', None)
if mtaskb:
mtask = mtaskb.mtask
attrs['mtask'] = mtask
attrs['handle_user'] = mtaskb.handle_user
if mtask:
attrs['mgroup'] = mtask.mgroup
attrs['material_in'] = mtask.material_in
material_out = mtask.material_out
attrs['material_out'] = material_out
if mtask.start_date == mtask.end_date:
attrs['handle_date'] = mtask.end_date
else:
mgroup = attrs['mgroup']
material_out = attrs['material_out']
if not (mgroup and material_out):
raise ParseError('缺少工段或产物!')
handle_user = attrs.get('handle_user', None)
if handle_user is None and hasattr(self, "request"):
handle_user = self.request.user
return attrs
class MlogInitSerializer(CustomModelSerializer):
class Meta:
model = Mlog
fields = ['id',
'work_start_time', 'work_end_time', 'mgroup', 'reminder_interval_list',
'route', 'equipment', 'handle_user', 'note', 'supplier', 'test_file', 'test_user', 'test_time', 'oinfo_json', 'is_fix']
read_only_fields = ["mtype"]
extra_kwargs = {
'work_start_time': {'required': True},
'route':{'required': False},
'mgroup': {'required': True},
'mtype': {'required': True}
}
def validate(self, attrs):
route: Route = attrs.get('route', None)
mgroup: Mgroup = attrs['mgroup']
is_fix:bool = attrs.get('is_fix', False)
attrs['mtype'] = mgroup.mtype
if is_fix:
attrs["route"] = None
elif route is None:
raise ParseError('缺少工艺路线')
if route and route.process != mgroup.process:
raise ParseError('工序不匹配')
if is_fix:
attrs['hour_work'] = None
attrs['material_in'] = None
attrs['material_out'] = None
if route:
attrs['hour_work'] = route.hour_work
attrs['material_in'] = route.material_in
attrs['material_out'] = route.material_out
attrs['fill_way'] = Mlog.MLOG_23
if attrs['mtype'] == Mlog.MTYPE_OUT:
supplier = attrs.get('supplier', None)
if not supplier:
raise ParseError('外协必须选择外协单位')
if attrs.get('work_end_time', None):
attrs['handle_date'] = localdate(attrs['work_end_time'])
if attrs["material_out"]:
attrs["qct"] = Qct.get(attrs["material_out"], "process")
return attrs
class MlogChangeSerializer(CustomModelSerializer):
class Meta:
model = Mlog
fields = ['id', 'work_end_time', 'handle_user', 'note', 'oinfo_json', 'test_file', 'test_user', 'test_time', 'equipment']
def validate(self, attrs):
if attrs.get('work_end_time', None):
attrs['handle_date'] = localdate(attrs['work_end_time'])
return attrs
class CountJsonSerializer(serializers.Serializer):
count_use = serializers.IntegerField(min_value=0, required=True)
floor = serializers.IntegerField(min_value=1, required=True)
count_test = serializers.IntegerField(min_value=0, required=True)
count_notok = serializers.IntegerField(min_value=0, required=True)
class CountJsonFromSerializer(serializers.Serializer):
start = serializers.IntegerField(min_value=0, required=True)
end = serializers.IntegerField(min_value=0, required=True)
count_t = serializers.IntegerField(min_value=0, required=True, label="总数")
class MlogbInSerializer(CustomModelSerializer):
mlogbdefect = MlogbDefectSerializer(many=True, required=False)
count_json_from = CountJsonFromSerializer(required=False, many=True)
class Meta:
model = Mlogb
fields = ['id', 'mlog', 'mtask', 'wm_in', 'count_use', 'count_pn_jgqbl',
'count_break', 'note', "parent", "mlogbdefect", "count_json_from"]
extra_kwargs = {'count_use': {'required': True}, 'mtask': {'required': False},
'wm_in': {'required': True, "allow_empty": False}}
def validate(self, attrs):
if attrs["count_use"] < 0 or attrs["count_pn_jgqbl"] < 0 or attrs.get("count_break", 0) < 0:
raise ParseError('存在负数!')
mlog:Mlog = attrs['mlog']
is_fix = mlog.is_fix
mtask: Mtask = attrs.get("mtask", None)
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
raise ParseError('该任务非下达中不可选择')
wm_in: WMaterial = attrs['wm_in']
if wm_in is None:
raise ParseError("请选择相应车间库存!")
if is_fix: # 返修或复检
if wm_in.state in [WMaterial.WM_REPAIR, WMaterial.WM_NOTOK]:
raise ParseError('返修或复检需使用返修品/不合格品')
elif wm_in.state != WMaterial.WM_OK:
raise ParseError('非合格品不可使用')
if mtask and mlog.route != mtask.route:
raise ParseError('工序不匹配')
route = mlog.route
attrs['material_in'] = wm_in.material
attrs['batch'] = wm_in.batch
attrs["batch_ofrom"] = wm_in.batch_ofrom
attrs["material_ofrom"] = wm_in.material_ofrom
if route and route.batch_bind and mtask is not None:
if not WMaterial.mat_in_qs(mtask).filter(id=wm_in.id).exists():
raise ParseError('该车间库存非本任务使用')
return attrs
def create(self, validated_data):
mlog: Mlog = validated_data['mlog']
mtask: Mtask = validated_data.get("mtask", None)
mlogbdefect = validated_data.pop("mlogbdefect", None)
if Mlogb.objects.filter(mlog=mlog, mtask=mtask, wm_in=validated_data['wm_in'], parent=None).exists():
raise ParseError('该记录已存在')
if mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑')
with transaction.atomic():
ins:Mlogb = super().create(validated_data)
if mlog.is_fix:
if mlog.material_in is None:
mlog.material_in = ins.material_in
mlog.material_out = ins.material_in
mlog.save(update_fields=["material_in", "material_out"])
elif mlog.material_in != ins.material_in:
raise ParseError('该记录必须使用同一物料')
if mlogbdefect is not None and ins.material_in.tracking == Material.MA_TRACKING_BATCH:
mlogb_defect_objects = [
MlogbDefect(**{**item, "mlogb": ins, "id": idWorker.get_id()})
for item in mlogbdefect if item["count"] > 0
]
if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
ins.cal_count_pn_jgqbl()
return ins
class MlogbInUpdateSerializer(CustomModelSerializer):
mlogbdefect = MlogbDefectSerializer(many=True, required=False)
class Meta:
model = Mlogb
fields = ['id', 'count_use', 'count_pn_jgqbl', 'note', 'mlogbdefect', "need_inout"]
def validate(self, attrs):
if attrs["count_use"] < 0 or attrs["count_pn_jgqbl"] < 0:
raise ParseError('存在负数!')
return attrs
def update(self, instance, validated_data):
mlog: Mlog = instance.mlog
mlogbdefect = validated_data.pop("mlogbdefect", None)
if mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑')
ins = super().update(instance, validated_data)
if mlogbdefect is not None and ins.material_in.tracking == Material.MA_TRACKING_BATCH:
MlogbDefect.objects.filter(mlogb=ins).delete()
mlogb_defect_objects = [
MlogbDefect(**{**item, "mlogb": ins, "id": idWorker.get_id()})
for item in mlogbdefect if item["count"] > 0
]
if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
ins.cal_count_notok()
return ins
class MlogbwCreateUpdateSerializer(CustomModelSerializer):
ftest = FtestProcessSerializer(required=False)
class Meta:
model = Mlogbw
fields = ["id", "number", "wpr", "note", "mlogb", "ftest", "equip", "work_start_time", "work_end_time", "mlogbw_from"]
read_only_fields = ["mlogbw_from"]
def validate(self, attrs):
mlogb:Mlogb = attrs["mlogb"]
if mlogb.mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑')
wpr:Wpr = attrs.get("wpr", None)
in_or_out, tracking = mlogb.get_tracking()
if tracking != Material.MA_TRACKING_SINGLE:
raise ParseError('非单件追踪不可使用')
if in_or_out == 'in' and not wpr:
raise ParseError('请选择相应产品')
return attrs
def save_ftest(self, mlogbw, ftest_data):
ftest = mlogbw.ftest
if not ftest:
ftest_sr = FtestProcessSerializer(data=ftest_data)
ftest = ftest_sr.create(ftest_data)
mlogbw.ftest = ftest
mlogbw.save()
else:
ftest_sr = FtestProcessSerializer()
ftest_sr.update(instance=ftest, validated_data=ftest_data)
return mlogbw
@transaction.atomic
def create(self, validated_data):
wpr: Wpr = validated_data.get("wpr", None)
if wpr:
mlogb: Mlogb = validated_data["mlogb"]
if Mlogbw.objects.filter(mlogb=mlogb, wpr=wpr).exists():
raise ParseError('该产品已选入')
ftest_data = validated_data.pop("ftest", None)
mlogbw = super().create(validated_data)
if ftest_data:
mlogbw = self.save_ftest(mlogbw, ftest_data)
return mlogbw
@transaction.atomic
def update(self, instance, validated_data):
validated_data.pop("mlogb")
ftest_data = validated_data.pop("ftest", None)
mlogbw = super().update(instance, validated_data)
if ftest_data:
mlogbw = self.save_ftest(mlogbw, ftest_data)
return mlogbw
class MlogbOutUpdateSerializer(CustomModelSerializer):
mlogbdefect = MlogbDefectSerializer(many=True, required=False)
count_json = CountJsonSerializer(required=False, many=True)
class Meta:
model = Mlogb
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE + ['mlog', 'mtask', 'wm_in', 'material_in', 'material_out',
'count_use', 'count_break', 'count_pn_jgqbl', 'mlogbdefect', "qct", "batch", "count_json"]
# def create(self, validated_data):
# material_out:Material = validated_data["material_out"]
# mlogbdefect = validated_data.pop("mlogbdefect", [])
# with transaction.atomic():
# ins = super().create(validated_data)
# if mlogbdefect and material_out.tracking == Material.MA_TRACKING_BATCH:
# count_notok = 0
# mlogbdefect_new = [item for item in mlogbdefect if item["count"] > 0]
# for item in mlogbdefect_new:
# defect:Defect = item["defect"]
# MlogbDefect.objects.create(mlogb=ins, **item)
# if defect.cate == Defect.DEFECT_NOTOK:
# count_notok +=1
# ins.count_notok = count_notok
# ins.count_ok = ins.count_real - ins.count_notok
# ins.save()
# else:
# raise ParseError("mlogbdefect仅支持批次件")
# return ins
@transaction.atomic
def update(self, instance, validated_data):
mlogbdefect = validated_data.pop("mlogbdefect", None)
with transaction.atomic():
ins:Mlogb = super().update(instance, validated_data)
if ins.need_inout is False:
if ins.mlogb_from:
if Mlogb.objects.filter(mlog=ins.mlog, material_out__isnull=False, mlogb_from=ins.mlogb_from).count() == 1:
ins_from =Mlogb.objects.filter(mlog=ins.mlog, material_out__isnull=False, mlogb_from=ins.mlogb_from).first()
ins_from.need_inout = False
ins_from.save(update_fields=["need_inout"])
else:
raise ParseError("对应消耗的产出有多个, 需手动指定消耗是否出库")
else:
raise ParseError("该产出需入库!")
if mlogbdefect is not None and ins.material_out.tracking == Material.MA_TRACKING_BATCH:
MlogbDefect.objects.filter(mlogb=ins).delete()
mlogb_defect_objects = [
MlogbDefect(**{**item, "mlogb": ins, "id": idWorker.get_id()})
for item in mlogbdefect if item["count"] > 0
]
if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
ins.cal_count_notok()
return ins
def validate(self, attrs):
mlogbdefect = attrs.get("mlogbdefect", [])
if mlogbdefect:
attrs.pop("count_notok_json", None)
for i in attrs:
if 'count_n_' in i:
attrs.pop(i, None)
else:
count_notok_json = attrs.get('count_notok_json', [])
# count_notok_json字段处理
if count_notok_json:
# 先置0字段
for i in attrs:
if 'count_n_' in i:
i = 0
count_notok_dict = {}
for item in count_notok_json:
notok = item['notok']
count = item['count']
full_notok = f'count_n_{notok}'
if not hasattr(Mlogb, full_notok):
raise ParseError(f'{notok}-该不合格项不存在')
if full_notok in count_notok_dict:
count_notok_dict[full_notok] = count_notok_dict[full_notok] + count
else:
count_notok_dict[full_notok] = count
for k, v in count_notok_dict.items():
attrs[k] = v
count_notok = 0
for i in attrs:
if 'count_n_' in i:
if not hasattr(Mlogb, i):
raise ParseError(f'{i}不存在')
count_notok = count_notok + attrs[i]
attrs['count_notok'] = count_notok
if attrs['count_real'] >= attrs['count_ok'] + attrs['count_notok']:
pass
else:
raise ParseError('生产数量不能小于合格数量')
return attrs
class MlogRevertSerializer(serializers.Serializer):
change_reason = serializers.CharField(label='撤回原因')
class MlogRelatedSerializer(serializers.Serializer):
mtask = serializers.PrimaryKeyRelatedField(
label='小任务ID', queryset=Mtask.objects.all())
class DeptBatchSerializer(serializers.Serializer):
belong_dept_name = serializers.CharField(label='车间名称')
class Handoverbwserializer(CustomModelSerializer):
class Meta:
model = Handoverbw
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS_BASE + ["handoverb", "number"]
extra_kwargs = {'wpr': {'required': True}}
class HandoverbSerializer(CustomModelSerializer):
notok_sign = serializers.CharField(source='wm.notok_sign', read_only=True)
defect_name = serializers.CharField(source="wm.defect.name", read_only=True)
handoverbw = Handoverbwserializer(many=True, required=False)
class Meta:
model = Handoverb
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE + ['handover']
extra_kwargs = {'wm': {'required': True}}
class HandoverSerializer(CustomModelSerializer):
# wm = serializers.PrimaryKeyRelatedField(
# label='车间库存ID', queryset=WMaterial.objects.all())
# material = serializers.PrimaryKeyRelatedField(
# required=True, label='物料ID', queryset=Material.objects.all())
send_user_name = serializers.CharField(
source='send_user.name', read_only=True)
recive_user_name = serializers.CharField(
source='recive_user.name', read_only=True)
recive_dept_name = serializers.CharField(
source='recive_dept', read_only=True)
send_mgroup_name = serializers.CharField(source='send_mgroup.name', read_only=True)
recive_mgroup_name = serializers.CharField(source='recive_mgroup.name', read_only=True)
material_ = MaterialSimpleSerializer(source='material', read_only=True)
material_name = serializers.StringRelatedField(
source='material', read_only=True)
wm_notok_sign = serializers.CharField(source='wm.notok_sign', read_only=True)
handoverb = HandoverbSerializer(many=True, required=False)
def validate(self, attrs):
if "mtype" not in attrs:
attrs['mtype'] = Handover.H_NORMAL
mtype = attrs["mtype"]
if 'type' not in attrs:
attrs['type'] = Handover.H_NORMAL
if attrs["type"] == Handover.H_CHANGE:
if "material_changed" not in attrs:
raise ParseError("必须指定改版后的物料")
if mtype == Handover.H_MERGE:
new_state = None
new_wm:WMaterial = attrs.get("new_wm", None)
if new_wm:
attrs['new_batch'] = new_wm.batch
new_state = new_wm.state
new_defect = new_wm.defect
if not attrs.get("new_batch", None):
raise ParseError("必须指定合并后的批次")
wm:WMaterial = attrs.get('wm', None)
handoverb = attrs.get('handoverb', [])
if wm and not handoverb:
attrs['handoverb'] = [{"wm": wm, "count": attrs["count"] }]
handoverb = attrs['handoverb']
attrs['batch'] = wm.batch
elif handoverb:
wm: WMaterial = handoverb[0]["wm"]
if wm:
pass
else:
raise ParseError('必须指定车间库存')
attrs['material'] = wm.material
attrs['send_dept'] = wm.belong_dept
if wm.mgroup:
attrs['send_mgroup'] = wm.mgroup
if attrs['material'].process and attrs['material'].process.into_wm_mgroup and 'recive_mgroup' not in attrs:
raise ParseError('必须指定交接工段')
if 'recive_mgroup' in attrs and attrs['recive_mgroup']:
attrs['recive_dept'] = attrs['recive_mgroup'].belong_dept
if not attrs.get('recive_dept', None) and not attrs.get('recive_mgroup', None):
raise ParseError('必须指定收料车间或收料工段')
if not attrs.get('send_dept', None) and not attrs.get('send_mgroup', None):
raise ParseError('必须指定送料车间或送料工段')
t_count = 0
tracking = attrs["material"].tracking
for ind, item in enumerate(attrs['handoverb']):
if item["count"] > 0:
pass
else:
raise ParseError(f'{ind+1}行-交接数量必须大于0')
wm = item["wm"]
if mtype == Handover.H_MERGE:
if new_state is None:
new_mat = wm.material
new_state = wm.state
new_defect = wm.defect
else:
if new_mat != wm.material:
raise ParseError(f'{ind+1}行-合并的物料不一致')
if new_state != wm.state:
raise ParseError(f'{ind+1}行-合并的物料状态不一致')
if new_defect != wm.defect:
raise ParseError(f'{ind+1}行-合并的物料缺陷不一致')
if tracking == Material.MA_TRACKING_SINGLE:
handoverbw = item.get("handoverbw", [])
if handoverbw:
t_count += len(handoverbw)
elif wm.count == item["count"]:
t_count += item["count"]
else:
raise ParseError(f'{ind+1}行-请提供交接物料明细编号')
else:
t_count += item["count"]
# if wm.mgroup and wm.mgroup != attrs['send_mgroup']:
# raise ParseError(f'第{ind+1}物料与交接工段不一致')
# if wm.belong_dept and wm.belong_dept != attrs['send_dept']:
# raise ParseError(f'第{ind+1}物料与交接部门不一致')
if attrs["material"] != wm.material:
raise ParseError(f'{ind+1}物料与交接物料不一致')
# if wm.state != WMaterial.WM_OK and attrs['type'] in [Handover.H_NORMAL, Handover.H_TEST]:
# raise ParseError(f'第{ind+1}物料不合格,不能进行正常/检验交接')
if wm.count_xtest is not None:
raise ParseError(f'{ind+1}物料检验中,不能进行交接')
attrs["count"] = t_count
if attrs['type'] == Handover.H_REPAIR:
# 返修时还是该物料
recive_mgroup = attrs.get("recive_mgroup", None)
if recive_mgroup is None:
raise ParseError('返工交接需指定工段')
return attrs
class Meta:
model = Handover
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + ["mlog"]
extra_kwargs = {
"type": {"required": False},
"wm": {"required": False},
"send_dept": {"required": False},
"recive_mgroup": {"required": False},
"recive_dept": {"required": False},
"material": {"required": False},
"material_changed": {"required": False},
"batch": {"required": False},
"count": {"required": False},
"count_eweight": {"required": False}
}
def create(self, validated_data):
handoverb = validated_data.pop('handoverb', [])
with transaction.atomic():
ins = super().create(validated_data)
mtype = validated_data["mtype"]
for ind, item in enumerate(handoverb):
wm = item["wm"]
count = item["count"]
handoverbw = item.pop("handoverbw", [])
if mtype == Handover.H_DIV:
if not item["batch"]:
raise ParseError(f'{ind+1}行-请提供拆批批次号')
if ins.wm is None:
raise ParseError("请提供拆批库存")
handoverb = Handoverb.objects.create(handover=ins, batch=item["batch"], count=count, wm=ins.wm)
else:
handoverb = Handoverb.objects.create(handover=ins, wm=wm, count=count, batch=wm.batch)
if wm.material.tracking == Material.MA_TRACKING_SINGLE:
if handoverbw:
handoverb.count = len(handoverbw)
handoverb.save()
for item in handoverbw:
wpr = item["wpr"]
Handoverbw.objects.get_or_create(wpr=wpr, handoverb=handoverb, defaults={"number":wpr.number, "note": item.get("note", None)})
elif count == wm.count:
for item in Wpr.get_qs_by_wm(wm):
Handoverbw.objects.get_or_create(wpr=item, handoverb=handoverb, defaults={"number":item.number})
else:
raise ParseError(f'{ind+1}行-请提供交接物料明细编号')
return ins
def update(self, instance, validated_data):
handoverb = validated_data.pop('handoverb', [])
with transaction.atomic():
insx = super().update(instance, validated_data)
Handoverb.objects.filter(handover=instance).delete()
for ind, item in enumerate(handoverb):
wm = item["wm"]
count = item["count"]
handoverbw = item.pop("handoverbw", [])
if validated_data["mtype"] == Handover.H_DIV:
if not item["batch"]:
raise ParseError(f'{ind+1}行-请提供拆批批次号')
if insx.wm is None:
raise ParseError("请提供拆批库存")
hb, _ = Handoverb.objects.get_or_create(handover=instance, batch=item["batch"], wm=insx.wm,
defaults={"count": count})
else:
hb, _ = Handoverb.objects.get_or_create(handover=instance, wm=wm, defaults={"count": count,
"batch": wm.batch})
if wm.material.tracking == Material.MA_TRACKING_SINGLE:
Handoverbw.objects.filter(handoverb=hb).delete()
if handoverbw:
hb.count = len(handoverbw)
hb.save()
for item in handoverbw:
wpr = item["wpr"]
Handoverbw.objects.get_or_create(wpr=wpr, handoverb=hb, defaults={"number": wpr.number, "note": item.get("note", None)})
elif count == wm.count:
wpr_qs = Wpr.get_qs_by_wm(wm)
for item in wpr_qs:
Handoverbw.objects.get_or_create(wpr=item, handoverb=handoverb,
defaults={"number": item.number})
else:
raise ParseError(f'{ind+1}行-请提供交接物料明细')
return instance
class HandoverUpdateSerializer(CustomModelSerializer):
class Meta:
model = Handover
fields = ['id', 'send_date', 'send_user', 'count', 'count_eweight', 'recive_user', 'note']
class GenHandoverSerializer(serializers.Serializer):
mlogs = serializers.PrimaryKeyRelatedField(
label='mlog的ID列表', queryset=Mlog.objects.all(), many=True)
recive_dept = serializers.PrimaryKeyRelatedField(
label='交送车间', queryset=Dept.objects.all())
recive_user = serializers.PrimaryKeyRelatedField(
label='接收人', queryset=User.objects.all())
send_user = serializers.PrimaryKeyRelatedField(
label='交送人', queryset=User.objects.all())
send_date = serializers.DateField(label='交送日期')
class GenHandoverWmSerializer(serializers.Serializer):
wm = serializers.PrimaryKeyRelatedField(
label='车间物料ID', queryset=WMaterial.objects.all())
send_mgroup = serializers.PrimaryKeyRelatedField(
label='送料工段ID', queryset=Mgroup.objects.all())
recive_dept = serializers.PrimaryKeyRelatedField(
label='交送车间', queryset=Dept.objects.all())
recive_user = serializers.PrimaryKeyRelatedField(
label='接收人', queryset=User.objects.all())
send_user = serializers.PrimaryKeyRelatedField(
label='交送人', queryset=User.objects.all())
send_date = serializers.DateField(label='交送日期')
count = serializers.IntegerField(label='交送数量')
def validate(self, attrs):
if attrs['count'] <= 1:
raise ParseError('交送数量必须大于1')
return attrs
class MlogAnaSerializer(serializers.Serializer):
belong_dept_name = serializers.CharField(label='车间名', required=False)
start_date = serializers.DateField(label='开始日期', required=True)
end_date = serializers.DateField(label='结束日期', required=True)
material_cate = serializers.CharField(label='物料系列', required=False)
class AttLogSerializer(CustomModelSerializer):
mgroup_name = serializers.CharField(
source='sflog.mgroup.name', read_only=True)
user_name = serializers.CharField(source='user.name', read_only=True)
post_name = serializers.CharField(source='post.name', read_only=True)
belong_dept_name = serializers.CharField(
source='sflog.mgroup.belong_dept.name', read_only=True)
class Meta:
model = AttLog
fields = '__all__'
class FmlogSerializer(CustomModelSerializer):
# routepack_name = serializers.CharField(
# source='mtask.route.routepack.name', read_only=True)
route_name = serializers.StringRelatedField(source="route", read_only=True)
mgroup_name = serializers.CharField(source='mgroup.name', read_only=True)
mtask_number = serializers.CharField(source='mtask.number', read_only=True)
class Meta:
model = Fmlog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS
def validate(self, attrs):
is_fix = attrs.get("is_fix", False)
if is_fix:
attrs["mtask"] = None
elif not attrs.get("mtask", None) and not attrs.get("route", None):
raise ParseError("请选择任务或工艺步骤")
mtask: Mtask = attrs['mtask']
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
raise ParseError('该任务非下达中不可选择')
if mtask:
attrs["route"] = mtask.route
return attrs
class FmlogUpdateSerializer(CustomModelSerializer):
class Meta:
model = Fmlog
fields = ['id', 'note', 'enabled']
class MlogTCreateSerializer(CustomModelSerializer):
pass
class BatchStSerializer(CustomModelSerializer):
class Meta:
model = BatchSt
fields = "__all__"
class HandoverMgroupSerializer(serializers.Serializer):
material = serializers.CharField(label="物料ID")
type = serializers.IntegerField(label="交送类型")
class MlogUserSerializer(CustomModelSerializer):
handle_user_name = serializers.CharField(source='handle_user.name', read_only=True)
process_name = serializers.CharField(source='process.name', read_only=True)
shift_name = serializers.CharField(source='shift.name', read_only=True)
class Meta:
model = MlogUser
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE
def create(self, validated_data):
mlog:Mlog = validated_data["mlog"]
if mlog.submit_time is not None:
raise ParseError("该日志已提交")
process:Process = validated_data["process"]
if mlog.route:
p = mlog.route.process
if process.parent != p:
raise ParseError("该步骤不匹配")
else:
raise ParseError("该日志没有工艺步骤")
if MlogUser.objects.filter(mlog=mlog, process=process).exists():
raise ParseError("该工序已选择")
return super().create(validated_data)
class BatchLogSerializer(CustomModelSerializer):
source_batch = serializers.CharField(source='source.batch', read_only=True)
target_batch = serializers.CharField(source='target.batch', read_only=True)
class Meta:
model = BatchLog
fields = "__all__"