feat: inm和wpm关于事务处理的修改

This commit is contained in:
caoqianming 2025-09-16 10:25:52 +08:00
parent 9bf44c4211
commit 7a82844842
4 changed files with 342 additions and 363 deletions

View File

@ -39,8 +39,7 @@ def correct_mb_count_notok():
count_notok = mi.count_n_zw + mi.count_n_tw + mi.count_n_qp + mi.count_n_wq + mi.count_n_dl + mi.count_n_pb + mi.count_n_dxt + mi.count_n_js + mi.count_n_qx + mi.count_n_zz + mi.count_n_ysq + mi.count_n_hs + mi.count_n_b + mi.count_n_qt count_notok = mi.count_n_zw + mi.count_n_tw + mi.count_n_qp + mi.count_n_wq + mi.count_n_dl + mi.count_n_pb + mi.count_n_dxt + mi.count_n_js + mi.count_n_qx + mi.count_n_zz + mi.count_n_ysq + mi.count_n_hs + mi.count_n_b + mi.count_n_qt
# 先处理库存 # 先处理库存
try: try:
with transaction.atomic(): MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok)
MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok) InmService.update_mb_after_test(mi)
InmService.update_mb_after_test(mi)
except ParseError as e: except ParseError as e:
MIOItem.objects.filter(id=mi.id).update(test_date=None) MIOItem.objects.filter(id=mi.id).update(test_date=None)

View File

@ -27,6 +27,7 @@ from apps.qm.serializers import FtestProcessSerializer
from apps.mtm.models import Material from apps.mtm.models import Material
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi from drf_yasg import openapi
from django.db import connection
# Create your views here. # Create your views here.
@ -151,6 +152,15 @@ class MIOViewSet(CustomModelViewSet):
'item_mio__a_mioitem__batch'] 'item_mio__a_mioitem__batch']
data_filter = True data_filter = True
@classmethod
def lock_and_check_can_update(cls, mio:MIO):
if not connection.in_atomic_block:
raise ParseError("请在事务中调用该方法")
mio:MIO = MIO.objects.select_for_update().get(id=mio.id)
if mio.submit_time is not None:
raise ParseError("该记录已提交无法更改")
return mio
def add_info_for_list(self, data): def add_info_for_list(self, data):
# 获取检验状态 # 获取检验状态
mio_dict = {} mio_dict = {}
@ -195,28 +205,29 @@ class MIOViewSet(CustomModelViewSet):
return super().perform_destroy(instance) return super().perform_destroy(instance)
@action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer) @action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer)
@transaction.atomic
def submit(self, request, *args, **kwargs): def submit(self, request, *args, **kwargs):
"""提交 """提交
提交 提交
""" """
ins = self.get_object() ins:MIO = self.get_object()
if ins.inout_date is None: if ins.inout_date is None:
raise ParseError('出入库日期未填写') raise ParseError('出入库日期未填写')
if ins.state != MIO.MIO_CREATE: if ins.state != MIO.MIO_CREATE:
raise ParseError('记录状态异常') raise ParseError('记录状态异常')
with transaction.atomic(): now = timezone.now()
now = timezone.now() ins.submit_user = request.user
updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=True).update( ins.submit_time = now
submit_time=now, update_time=now, state=MIO.MIO_SUBMITED, submit_user=request.user, update_by=request.user) ins.update_by = request.user
if updated_count == 1: ins.state = MIO.MIO_SUBMITED
InmService.update_inm(ins) ins.save()
else: InmService.update_inm(ins)
raise ParseError('记录正在处理中,请稍后再试')
InmService.update_material_count(ins) InmService.update_material_count(ins)
return Response(MIOListSerializer(instance=ins).data) return Response(MIOListSerializer(instance=ins).data)
@action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer) @action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer)
@transaction.atomic
def revert(self, request, *args, **kwargs): def revert(self, request, *args, **kwargs):
"""撤回 """撤回
@ -228,13 +239,12 @@ class MIOViewSet(CustomModelViewSet):
raise ParseError('记录状态异常') raise ParseError('记录状态异常')
if ins.submit_user != user: if ins.submit_user != user:
raise ParseError('非提交人不可撤回') raise ParseError('非提交人不可撤回')
with transaction.atomic(): ins.submit_user = None
updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=False).update( ins.update_by = user
submit_time=None, update_time=timezone.now(), state=MIO.MIO_CREATE, submit_user=None, update_by=request.user) ins.state = MIO.MIO_CREATE
if updated_count == 1: ins.submit_time = None
InmService.update_inm(ins, is_reverse=True) ins.save()
else: InmService.update_inm(ins, is_reverse=True)
raise ParseError('记录正在处理中,请稍后再试')
InmService.update_material_count(ins) InmService.update_material_count(ins)
return Response() return Response()
@ -355,10 +365,13 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode
]) ])
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
return super().list(request, *args, **kwargs) return super().list(request, *args, **kwargs)
def perform_create(self, serializer):
serializer.validated_data["mio"] = MIOViewSet.lock_and_check_can_update(serializer.validated_data['mio'])
return super().perform_create(serializer)
def perform_destroy(self, instance): def perform_destroy(self, instance):
if instance.mio.state != MIO.MIO_CREATE: MIOViewSet.lock_and_check_can_update(instance.mio)
raise ParseError('出入库记录非创建中不可删除')
if has_perm(self.request.user, ['mio.update']) is False and instance.mio.create_by != self.request.user: if has_perm(self.request.user, ['mio.update']) is False and instance.mio.create_by != self.request.user:
raise PermissionDenied('无权限删除') raise PermissionDenied('无权限删除')
return super().perform_destroy(instance) return super().perform_destroy(instance)
@ -490,20 +503,20 @@ class MIOItemwViewSet(CustomModelViewSet):
mioitem.count_notok = MIOItemw.objects.filter(mioitem=mioitem, ftest__is_ok=False).count() mioitem.count_notok = MIOItemw.objects.filter(mioitem=mioitem, ftest__is_ok=False).count()
mioitem.save() mioitem.save()
@transaction.atomic
def perform_create(self, serializer): def perform_create(self, serializer):
ins: MIOItemw = serializer.save() MIOViewSet.lock_and_check_can_update(serializer.validated_data['mioitem'].mio)
mioitem: MIOItem = ins.mioitem ins:MIOItemw = serializer.save()
self.cal_mioitem_count(mioitem) self.cal_mioitem_count(ins.mioitem)
@transaction.atomic
def perform_update(self, serializer): def perform_update(self, serializer):
mioitemw = serializer.save() ins:MIOItemw = serializer.instance
self.cal_mioitem_count(mioitemw.mioitem) MIOViewSet.lock_and_check_can_update(ins.mioitem.mio)
ins:MIOItemw = serializer.save()
self.cal_mioitem_count(ins.mioitem)
@transaction.atomic
def perform_destroy(self, instance: MIOItemw): def perform_destroy(self, instance: MIOItemw):
mioitem = instance.mioitem mioitem = instance.mioitem
MIOViewSet.lock_and_check_can_update(mioitem.mio)
ftest = instance.ftest ftest = instance.ftest
instance.delete() instance.delete()
if ftest: if ftest:

View File

@ -9,19 +9,18 @@ def correct_tuihuo_log():
mlogs = Mlog.objects.filter(mgroup__name='管料退火', count_use=0) mlogs = Mlog.objects.filter(mgroup__name='管料退火', count_use=0)
for mlog in mlogs: for mlog in mlogs:
try: try:
with transaction.atomic(): count_use = mlog.count_ok + mlog.count_notok
count_use = mlog.count_ok + mlog.count_notok material_has = WMaterial.objects.get(
material_has = WMaterial.objects.get( batch=mlog.batch, material=mlog.material_in, belong_dept=mlog.mgroup.belong_dept)
batch=mlog.batch, material=mlog.material_in, belong_dept=mlog.mgroup.belong_dept) material_has.count = material_has.count - count_use
material_has.count = material_has.count - count_use if material_has.count >= 0:
if material_has.count >= 0: if material_has.count == 0:
if material_has.count == 0: material_has.delete()
material_has.delete() else:
else: material_has.save()
material_has.save() mlog.count_real = count_use
mlog.count_real = count_use mlog.count_use = count_use
mlog.count_use = count_use mlog.save()
mlog.save() print(f'{mlog.id}-矫正成功')
print(f'{mlog.id}-矫正成功')
except Exception as e: except Exception as e:
print(f'{mlog.id}-矫正出错:{e}') print(f'{mlog.id}-矫正出错:{e}')

View File

@ -52,40 +52,36 @@ class StLogSerializer(CustomModelSerializer):
def create(self, validated_data): def create(self, validated_data):
current_sflog_id = validated_data.pop('current_sflog') current_sflog_id = validated_data.pop('current_sflog')
current_note = validated_data.pop('current_note', '') current_note = validated_data.pop('current_note', '')
with transaction.atomic(): sflog = get_sflog(
sflog = get_sflog( validated_data['mgroup'], validated_data['start_time'])
validated_data['mgroup'], validated_data['start_time']) if current_sflog_id != sflog.id:
if current_sflog_id != sflog.id: raise ParseError('值班时间与发生时间不一致')
raise ParseError('值班时间与发生时间不一致') instance = super().create(validated_data)
instance = super().create(validated_data) instance.sflog = sflog
instance.sflog = sflog instance.save()
instance.save() SfLogExp.objects.create(
SfLogExp.objects.create( sflog=sflog, stlog=instance, create_by=self.context['request'].user, note=current_note)
sflog=sflog, stlog=instance, create_by=self.context['request'].user, note=current_note) return instance
return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
if instance.is_shutdown: # 停机不可编辑end_time if instance.is_shutdown: # 停机不可编辑end_time
validated_data.pop('end_time', None) validated_data.pop('end_time', None)
# if instance.end_time: validated_data.pop('mgroup', None)
# raise ParseError('该异常已结束无需编辑') validated_data.pop('start_time', None)
with transaction.atomic(): end_time = validated_data.pop('end_time', None)
validated_data.pop('mgroup', None) current_sflog = validated_data.pop('current_sflog')
validated_data.pop('start_time', None) current_note = validated_data.pop('current_note', '')
end_time = validated_data.pop('end_time', None) instance = super().update(instance, validated_data)
current_sflog = validated_data.pop('current_sflog') if end_time: # 需要把涉及到的sflog都拉入
current_note = validated_data.pop('current_note', '') cal_exp_duration_sec(instance.id)
instance = super().update(instance, validated_data) try:
if end_time: # 需要把涉及到的sflog都拉入 sflogexp = SfLogExp.objects.get(
cal_exp_duration_sec(instance.id) stlog=instance, sflog=current_sflog)
try: sflogexp.note = current_note
sflogexp = SfLogExp.objects.get( sflogexp.save()
stlog=instance, sflog=current_sflog) except SfLogExp.DoesNotExist:
sflogexp.note = current_note raise ParseError('该异常无需本班填写')
sflogexp.save() return instance
except SfLogExp.DoesNotExist:
raise ParseError('该异常无需本班填写')
return instance
def validate(self, attrs): def validate(self, attrs):
now = timezone.now() now = timezone.now()
@ -374,97 +370,97 @@ class MlogSerializer(CustomModelSerializer):
mlogbindefect = validated_data.pop('mlogindefect', None) mlogbindefect = validated_data.pop('mlogindefect', None)
if mtask and mtask.state != Mtask.MTASK_ASSGINED: if mtask and mtask.state != Mtask.MTASK_ASSGINED:
raise ParseError('该任务非下达中不可选择') raise ParseError('该任务非下达中不可选择')
with transaction.atomic():
mlogb = validated_data.pop('mlogb', []) mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().create(validated_data) instance: Mlog = super().create(validated_data)
## 返工没有加工前不良 ## 返工没有加工前不良
if instance.is_fix and instance.count_pn_jgqbl >0: if instance.is_fix and instance.count_pn_jgqbl >0:
raise ParseError("返工不支持加工前不良") raise ParseError("返工不支持加工前不良")
# 自动生成mlogb # 自动生成mlogb
batch_in = instance.batch batch_in = instance.batch
wm_in = instance.wm_in 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,
'route': instance.route,
'count_use': instance.count_use, 'count_break': instance.count_break,
'count_pn_jgqbl': instance.count_pn_jgqbl
}
if wm_in: if wm_in:
batch_in = wm_in.batch add_dict['batch_ofrom'] = wm_in.batch_ofrom
instance.batch = batch_in add_dict['material_ofrom'] = wm_in.material_ofrom
instance.save(update_fields=['batch']) mlogbin = Mlogb.objects.create(**add_dict)
mlogbin = None if mlogbindefect is not None:
if instance.material_in: # 如果有消耗 mlogbin_defect_objects = [
add_dict = { MlogbDefect(**{**item, "mlogb": mlogbin, "id": idWorker.get_id()})
'mlog': instance, 'batch': batch_in, 'wm_in': wm_in, for item in mlogbindefect if item["count"] > 0
'mtask': instance.mtask, 'material_in': instance.material_in, ]
'route': instance.route, if mlogbin_defect_objects:
'count_use': instance.count_use, 'count_break': instance.count_break, MlogbDefect.objects.bulk_create(mlogbin_defect_objects)
'count_pn_jgqbl': instance.count_pn_jgqbl mlogbin.cal_count_pn_jgqbl(cal_mlog=False)
}
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(cal_mlog=False)
# mlogb只用于组合件输出物填写 # mlogb只用于组合件输出物填写
brotherId_should_list = material_out.brothers brotherId_should_list = material_out.brothers
if brotherId_should_list: if brotherId_should_list:
if mlogb: if mlogb:
for item in mlogb: for item in mlogb:
if item['material_out'].id in brotherId_should_list: if item['material_out'].id in brotherId_should_list:
mlogbx = Mlogb.objects.create( mlogbx = Mlogb.objects.create(
mlog=instance, mlog=instance,
batch=instance.batch, batch=instance.batch,
route=instance.route, route=instance.route,
mtask=instance.mtask, mtask=instance.mtask,
material_out=item['material_out'], material_out=item['material_out'],
count_ok=item['count_ok']) count_ok=item['count_ok'])
if wm_in: if wm_in:
mlogbx.batch_ofrom = wm_in.batch_ofrom mlogbx.batch_ofrom = wm_in.batch_ofrom
mlogbx.material_ofrom = wm_in.material_ofrom mlogbx.material_ofrom = wm_in.material_ofrom
mlogbx.save(update_fields=["batch_ofrom", "material_ofrom"]) mlogbx.save(update_fields=["batch_ofrom", "material_ofrom"])
else:
raise ParseError('缺少产出物信息')
else: else:
# 生成产出物 raise ParseError('缺少产出物信息')
batch_out = validated_data.get('batch', None) else:
if batch_out: # 生成产出物
pass batch_out = validated_data.get('batch', None)
else: if batch_out:
batch_out = generate_new_batch(batch_in, instance) pass
else:
add_dict_2 = { batch_out = generate_new_batch(batch_in, instance)
'mlog': instance, 'batch': batch_out,
'mtask': instance.mtask, 'material_out': instance.material_out, add_dict_2 = {
'count_real': instance.count_real, 'route': instance.route, 'mlog': instance, 'batch': batch_out,
'count_ok': instance.count_ok, 'count_notok': instance.count_notok, 'mtask': instance.mtask, 'material_out': instance.material_out,
'count_break_t': instance.count_break_t, 'count_real': instance.count_real, 'route': instance.route,
'qct': instance.qct 'count_ok': instance.count_ok, 'count_notok': instance.count_notok,
} 'count_break_t': instance.count_break_t,
need_mdfect = False 'qct': instance.qct
if mlogdefect is not None: }
need_mdfect = True need_mdfect = False
else: if mlogdefect is not None:
for f in Mlogb._meta.fields: need_mdfect = True
if 'count_n_' in f.name: else:
add_dict_2[f.name] = getattr(instance, f.name) for f in Mlogb._meta.fields:
ddict = {} if 'count_n_' in f.name:
if wm_in: add_dict_2[f.name] = getattr(instance, f.name)
ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom} ddict = {}
if mlogbin: if wm_in:
ddict["mlogb_from"] = mlogbin ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}
mlogb, _ = Mlogb.objects.get_or_create(**add_dict_2, defaults=ddict) if mlogbin:
if need_mdfect: ddict["mlogb_from"] = mlogbin
mlogb_defect_objects = [ mlogb, _ = Mlogb.objects.get_or_create(**add_dict_2, defaults=ddict)
MlogbDefect(**{**item, "mlogb": mlogb, "id": idWorker.get_id()}) if need_mdfect:
for item in mlogdefect if item["count"] > 0 mlogb_defect_objects = [
] MlogbDefect(**{**item, "mlogb": mlogb, "id": idWorker.get_id()})
if mlogb_defect_objects: for item in mlogdefect if item["count"] > 0
MlogbDefect.objects.bulk_create(mlogb_defect_objects) ]
mlogb.cal_count_notok(cal_mlog=False) if mlogb_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
mlogb.cal_count_notok(cal_mlog=False)
instance.cal_mlog_count_from_mlogb() instance.cal_mlog_count_from_mlogb()
return instance return instance
@ -478,91 +474,91 @@ class MlogSerializer(CustomModelSerializer):
if instance.mtask: if instance.mtask:
validated_data.pop('handle_date', None) validated_data.pop('handle_date', None)
# validated_data.pop('handle_user', None) # validated_data.pop('handle_user', None)
with transaction.atomic():
mlogb = validated_data.pop('mlogb', []) mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().update(instance, validated_data) instance: Mlog = super().update(instance, validated_data)
## 返工没有加工前不良 ## 返工没有加工前不良
if instance.is_fix and instance.count_pn_jgqbl >0: if instance.is_fix and instance.count_pn_jgqbl >0:
raise ParseError("返工不支持加工前不良") raise ParseError("返工不支持加工前不良")
wm_in = instance.wm_in wm_in = instance.wm_in
batch_in = instance.batch batch_in = instance.batch
if wm_in: if wm_in:
batch_in = wm_in.batch batch_in = wm_in.batch
# 修改消耗 # 修改消耗
if instance.fill_way in [Mlog.MLOG_12, Mlog.MLOG_2]: if instance.fill_way in [Mlog.MLOG_12, Mlog.MLOG_2]:
# 自动生成mlogb # 自动生成mlogb
if instance.material_in: # 有消耗的情况 if instance.material_in: # 有消耗的情况
minx, _ = Mlogb.objects.get_or_create( minx, _ = Mlogb.objects.get_or_create(
mlog=instance, mlog=instance,
batch=batch_in, batch=batch_in,
wm_in=instance.wm_in, wm_in=instance.wm_in,
mtask=instance.mtask, mtask=instance.mtask,
material_in=instance.material_in 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(cal_mlog=False)
# 修改产出
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_real = instance.count_real
mox.count_ok = instance.count_ok
mox.count_notok = instance.count_notok
mox.count_break_t = instance.count_break_t
if wm_in: if wm_in:
mox.batch_ofrom = wm_in.batch minx.batch_ofrom = wm_in.batch_ofrom
mox.material_ofrom = wm_in.material_ofrom minx.material_ofrom = wm_in.material_ofrom
need_mdefect=False minx.count_use = instance.count_use
if mlogdefect is not None: minx.count_break = instance.count_break
need_mdefect = True minx.count_pn_jgqbl = instance.count_pn_jgqbl
else: minx.qct = instance.qct
for f in Mlogb._meta.fields: minx.save()
if 'count_n_' in f.name: Mlogb.objects.filter(mlog=instance, material_in__isnull=False).exclude(id=minx.id).delete()
setattr(mox, f.name, getattr(instance, f.name)) if mlogbindefect is not None:
mox.save() mlogbin_defect_objects = [
Mlogb.objects.filter(mlog=instance, material_out__isnull=False).exclude(id=mox.id).delete() MlogbDefect(**{**item, "mlogb": minx, "id": idWorker.get_id()})
if need_mdefect: for item in mlogbindefect if item["count"] > 0
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: if mlogbin_defect_objects:
MlogbDefect.objects.bulk_create(mlogb_defect_objects) MlogbDefect.objects.bulk_create(mlogbin_defect_objects)
mox.cal_count_notok(cal_mlog=False) minx.cal_count_pn_jgqbl(cal_mlog=False)
# 修改产出
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_real = instance.count_real
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(cal_mlog=False)
instance.cal_mlog_count_from_mlogb() instance.cal_mlog_count_from_mlogb()
return instance return instance
@ -785,24 +781,16 @@ class MlogbInSerializer(CustomModelSerializer):
raise ParseError('该记录已存在') raise ParseError('该记录已存在')
if mlog.submit_time is not None: if mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑') raise ParseError('生产日志已提交不可编辑')
with transaction.atomic():
ins:Mlogb = super().create(validated_data) ins:Mlogb = super().create(validated_data)
# if mlog.is_fix: if mlogbdefect is not None and ins.material_in.tracking == Material.MA_TRACKING_BATCH:
# if mlog.material_in is None: mlogb_defect_objects = [
# mlog.material_in = ins.material_in MlogbDefect(**{**item, "mlogb": ins, "id": idWorker.get_id()})
# mlog.material_out = ins.material_in for item in mlogbdefect if item["count"] > 0
# mlog.save(update_fields=["material_in", "material_out"]) ]
# elif mlog.material_in != ins.material_in: if mlogb_defect_objects:
# raise ParseError('该记录必须使用同一物料') MlogbDefect.objects.bulk_create(mlogb_defect_objects)
ins.cal_count_pn_jgqbl(cal_mlog=False)
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(cal_mlog=False)
return ins return ins
class MlogbInUpdateSerializer(CustomModelSerializer): class MlogbInUpdateSerializer(CustomModelSerializer):
@ -1056,57 +1044,38 @@ class MlogbOutUpdateSerializer(CustomModelSerializer):
fields = "__all__" fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE + ['mlog', 'mtask', 'wm_in', 'material_in', 'material_out', read_only_fields = EXCLUDE_FIELDS_BASE + ['mlog', 'mtask', 'wm_in', 'material_in', 'material_out',
'count_use', 'count_break', 'count_pn_jgqbl', 'mlogbdefect', "qct", "count_json"] 'count_use', 'count_break', 'count_pn_jgqbl', 'mlogbdefect', "qct", "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
def update(self, instance, validated_data): def update(self, instance, validated_data):
mlog:Mlog = instance.mlog mlog:Mlog = instance.mlog
if mlog.submit_time is not None: if mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑') raise ParseError('生产日志已提交不可编辑')
mlogbdefect = validated_data.pop("mlogbdefect", None) mlogbdefect = validated_data.pop("mlogbdefect", None)
with transaction.atomic():
ins:Mlogb = super().update(instance, validated_data) ins:Mlogb = super().update(instance, validated_data)
if ins.need_inout is False: if ins.need_inout is False:
if ins.mlogb_from: if ins.mlogb_from:
if Mlogb.objects.filter(mlog=ins.mlog, material_out__isnull=False, mlogb_from=ins.mlogb_from).count() == 1: if Mlogb.objects.filter(mlog=ins.mlog, material_out__isnull=False, mlogb_from=ins.mlogb_from).count() == 1:
ins_from = ins.mlogb_from
ins_from.need_inout = False
ins_from.save(update_fields=["need_inout"])
else:
raise ParseError("对应消耗的产出有多个, 需手动指定消耗是否出库")
else:
raise ParseError("该产出需入库!")
else:
if ins.mlogb_from:
ins_from = ins.mlogb_from ins_from = ins.mlogb_from
ins_from.need_inout = True ins_from.need_inout = False
ins_from.save(update_fields=["need_inout"]) ins_from.save(update_fields=["need_inout"])
if mlogbdefect is not None and ins.material_out.tracking == Material.MA_TRACKING_BATCH: else:
MlogbDefect.objects.filter(mlogb=ins).delete() raise ParseError("对应消耗的产出有多个, 需手动指定消耗是否出库")
mlogb_defect_objects = [ else:
MlogbDefect(**{**item, "mlogb": ins, "id": idWorker.get_id()}) raise ParseError("该产出需入库!")
for item in mlogbdefect if item["count"] > 0 else:
] if ins.mlogb_from:
if mlogb_defect_objects: ins_from = ins.mlogb_from
MlogbDefect.objects.bulk_create(mlogb_defect_objects) ins_from.need_inout = True
ins.cal_count_notok(cal_mlog=False) ins_from.save(update_fields=["need_inout"])
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(cal_mlog=False)
return ins return ins
def validate(self, attrs): def validate(self, attrs):
@ -1325,69 +1294,68 @@ class HandoverSerializer(CustomModelSerializer):
def create(self, validated_data): def create(self, validated_data):
handoverb = validated_data.pop('handoverb', []) handoverb = validated_data.pop('handoverb', [])
with transaction.atomic(): ins = super().create(validated_data)
ins = super().create(validated_data) mtype = validated_data["mtype"]
mtype = validated_data["mtype"] for ind, item in enumerate(handoverb):
for ind, item in enumerate(handoverb): wm = item["wm"]
wm = item["wm"] count = item["count"]
count = item["count"] handoverbw = item.pop("handoverbw", [])
handoverbw = item.pop("handoverbw", []) if mtype == Handover.H_DIV:
if mtype == Handover.H_DIV: if not item["batch"]:
if not item["batch"]: raise ParseError(f'{ind+1}行-请提供拆批批次号')
raise ParseError(f'{ind+1}行-请提供拆批批次号') if ins.wm is None:
if ins.wm is None: raise ParseError("请提供拆批库存")
raise ParseError("请提供拆批库存") handoverb = Handoverb.objects.create(handover=ins, batch=item["batch"], count=count, wm=ins.wm)
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: else:
handoverb = Handoverb.objects.create(handover=ins, wm=wm, count=count, batch=wm.batch) raise ParseError(f'{ind+1}行-请提供交接物料明细编号')
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 return ins
def update(self, instance, validated_data): def update(self, instance, validated_data):
handoverb = validated_data.pop('handoverb', []) handoverb = validated_data.pop('handoverb', [])
with transaction.atomic():
insx = super().update(instance, validated_data) insx = super().update(instance, validated_data)
Handoverb.objects.filter(handover=instance).delete() Handoverb.objects.filter(handover=instance).delete()
for ind, item in enumerate(handoverb): for ind, item in enumerate(handoverb):
wm = item["wm"] wm = item["wm"]
count = item["count"] count = item["count"]
handoverbw = item.pop("handoverbw", []) handoverbw = item.pop("handoverbw", [])
if validated_data["mtype"] == Handover.H_DIV: if validated_data["mtype"] == Handover.H_DIV:
if not item["batch"]: if not item["batch"]:
raise ParseError(f'{ind+1}行-请提供拆批批次号') raise ParseError(f'{ind+1}行-请提供拆批批次号')
if insx.wm is None: if insx.wm is None:
raise ParseError("请提供拆批库存") raise ParseError("请提供拆批库存")
hb, _ = Handoverb.objects.get_or_create(handover=instance, batch=item["batch"], wm=insx.wm, hb, _ = Handoverb.objects.get_or_create(handover=instance, batch=item["batch"], wm=insx.wm,
defaults={"count": count}) 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: else:
hb, _ = Handoverb.objects.get_or_create(handover=instance, wm=wm, defaults={"count": count, raise ParseError(f'{ind+1}行-请提供交接物料明细')
"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 return instance
class HandoverUpdateSerializer(CustomModelSerializer): class HandoverUpdateSerializer(CustomModelSerializer):