diff --git a/apps/inm/correct.py b/apps/inm/correct.py index bd4587c9..6725404d 100644 --- a/apps/inm/correct.py +++ b/apps/inm/correct.py @@ -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 # 先处理库存 try: - with transaction.atomic(): - MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok) - InmService.update_mb_after_test(mi) + MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok) + InmService.update_mb_after_test(mi) except ParseError as e: MIOItem.objects.filter(id=mi.id).update(test_date=None) diff --git a/apps/inm/views.py b/apps/inm/views.py index 3b094a3f..d98a946a 100644 --- a/apps/inm/views.py +++ b/apps/inm/views.py @@ -27,6 +27,7 @@ from apps.qm.serializers import FtestProcessSerializer from apps.mtm.models import Material from drf_yasg.utils import swagger_auto_schema from drf_yasg import openapi +from django.db import connection # Create your views here. @@ -151,6 +152,15 @@ class MIOViewSet(CustomModelViewSet): 'item_mio__a_mioitem__batch'] 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): # 获取检验状态 mio_dict = {} @@ -195,28 +205,29 @@ class MIOViewSet(CustomModelViewSet): return super().perform_destroy(instance) @action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer) + @transaction.atomic def submit(self, request, *args, **kwargs): """提交 提交 """ - ins = self.get_object() + ins:MIO = self.get_object() if ins.inout_date is None: raise ParseError('出入库日期未填写') if ins.state != MIO.MIO_CREATE: raise ParseError('记录状态异常') - with transaction.atomic(): - now = timezone.now() - updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=True).update( - submit_time=now, update_time=now, state=MIO.MIO_SUBMITED, submit_user=request.user, update_by=request.user) - if updated_count == 1: - InmService.update_inm(ins) - else: - raise ParseError('记录正在处理中,请稍后再试') + now = timezone.now() + ins.submit_user = request.user + ins.submit_time = now + ins.update_by = request.user + ins.state = MIO.MIO_SUBMITED + ins.save() + InmService.update_inm(ins) InmService.update_material_count(ins) return Response(MIOListSerializer(instance=ins).data) @action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer) + @transaction.atomic def revert(self, request, *args, **kwargs): """撤回 @@ -228,13 +239,12 @@ class MIOViewSet(CustomModelViewSet): raise ParseError('记录状态异常') if ins.submit_user != user: raise ParseError('非提交人不可撤回') - with transaction.atomic(): - updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=False).update( - submit_time=None, update_time=timezone.now(), state=MIO.MIO_CREATE, submit_user=None, update_by=request.user) - if updated_count == 1: - InmService.update_inm(ins, is_reverse=True) - else: - raise ParseError('记录正在处理中,请稍后再试') + ins.submit_user = None + ins.update_by = user + ins.state = MIO.MIO_CREATE + ins.submit_time = None + ins.save() + InmService.update_inm(ins, is_reverse=True) InmService.update_material_count(ins) return Response() @@ -355,10 +365,13 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode ]) def list(self, 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): - if instance.mio.state != MIO.MIO_CREATE: - raise ParseError('出入库记录非创建中不可删除') + MIOViewSet.lock_and_check_can_update(instance.mio) if has_perm(self.request.user, ['mio.update']) is False and instance.mio.create_by != self.request.user: raise PermissionDenied('无权限删除') 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.save() - @transaction.atomic def perform_create(self, serializer): - ins: MIOItemw = serializer.save() - mioitem: MIOItem = ins.mioitem - self.cal_mioitem_count(mioitem) + MIOViewSet.lock_and_check_can_update(serializer.validated_data['mioitem'].mio) + ins:MIOItemw = serializer.save() + self.cal_mioitem_count(ins.mioitem) - @transaction.atomic def perform_update(self, serializer): - mioitemw = serializer.save() - self.cal_mioitem_count(mioitemw.mioitem) + ins:MIOItemw = serializer.instance + 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): mioitem = instance.mioitem + MIOViewSet.lock_and_check_can_update(mioitem.mio) ftest = instance.ftest instance.delete() if ftest: diff --git a/apps/wpm/correct.py b/apps/wpm/correct.py index 081192b2..06e94fff 100644 --- a/apps/wpm/correct.py +++ b/apps/wpm/correct.py @@ -9,19 +9,18 @@ def correct_tuihuo_log(): mlogs = Mlog.objects.filter(mgroup__name='管料退火', count_use=0) for mlog in mlogs: try: - with transaction.atomic(): - count_use = mlog.count_ok + mlog.count_notok - material_has = WMaterial.objects.get( - batch=mlog.batch, material=mlog.material_in, belong_dept=mlog.mgroup.belong_dept) - material_has.count = material_has.count - count_use - if material_has.count >= 0: - if material_has.count == 0: - material_has.delete() - else: - material_has.save() - mlog.count_real = count_use - mlog.count_use = count_use - mlog.save() - print(f'{mlog.id}-矫正成功') + count_use = mlog.count_ok + mlog.count_notok + material_has = WMaterial.objects.get( + batch=mlog.batch, material=mlog.material_in, belong_dept=mlog.mgroup.belong_dept) + material_has.count = material_has.count - count_use + if material_has.count >= 0: + if material_has.count == 0: + material_has.delete() + else: + material_has.save() + mlog.count_real = count_use + mlog.count_use = count_use + mlog.save() + print(f'{mlog.id}-矫正成功') except Exception as e: print(f'{mlog.id}-矫正出错:{e}') diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index e3a04818..75f086b7 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -52,40 +52,36 @@ class StLogSerializer(CustomModelSerializer): 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 + 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 + 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() @@ -374,97 +370,97 @@ class MlogSerializer(CustomModelSerializer): 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) - ## 返工没有加工前不良 - if instance.is_fix and instance.count_pn_jgqbl >0: - raise ParseError("返工不支持加工前不良") - # 自动生成mlogb - batch_in = instance.batch - wm_in = instance.wm_in + + mlogb = validated_data.pop('mlogb', []) + instance: Mlog = super().create(validated_data) + ## 返工没有加工前不良 + if instance.is_fix and instance.count_pn_jgqbl >0: + raise ParseError("返工不支持加工前不良") + # 自动生成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, + 'route': instance.route, + 'count_use': instance.count_use, 'count_break': instance.count_break, + 'count_pn_jgqbl': instance.count_pn_jgqbl + } 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: - 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) + 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只用于组合件输出物填写 - 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, - route=instance.route, - 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('缺少产出物信息') + # 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, + route=instance.route, + 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: - # 生成产出物 - 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, 'route': instance.route, - '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(cal_mlog=False) + 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, 'route': instance.route, + '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(cal_mlog=False) instance.cal_mlog_count_from_mlogb() return instance @@ -478,91 +474,91 @@ class MlogSerializer(CustomModelSerializer): 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) - ## 返工没有加工前不良 - if instance.is_fix and instance.count_pn_jgqbl >0: - raise ParseError("返工不支持加工前不良") - 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(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 + + mlogb = validated_data.pop('mlogb', []) + instance: Mlog = super().update(instance, validated_data) + ## 返工没有加工前不良 + if instance.is_fix and instance.count_pn_jgqbl >0: + raise ParseError("返工不支持加工前不良") + 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: - 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 + 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 mlogb_defect_objects: - MlogbDefect.objects.bulk_create(mlogb_defect_objects) - mox.cal_count_notok(cal_mlog=False) + 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: + 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() return instance @@ -785,24 +781,16 @@ class MlogbInSerializer(CustomModelSerializer): 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(cal_mlog=False) + + ins:Mlogb = super().create(validated_data) + 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 class MlogbInUpdateSerializer(CustomModelSerializer): @@ -1056,57 +1044,38 @@ class MlogbOutUpdateSerializer(CustomModelSerializer): 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", "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): mlog:Mlog = instance.mlog if mlog.submit_time is not None: raise ParseError('生产日志已提交不可编辑') 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 = 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: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 = ins.mlogb_from - ins_from.need_inout = True + ins_from.need_inout = 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) + else: + raise ParseError("对应消耗的产出有多个, 需手动指定消耗是否出库") + else: + raise ParseError("该产出需入库!") + else: + if ins.mlogb_from: + ins_from = ins.mlogb_from + ins_from.need_inout = True + 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 def validate(self, attrs): @@ -1325,69 +1294,68 @@ class HandoverSerializer(CustomModelSerializer): 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) + 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: - 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}行-请提供交接物料明细编号') + 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}) + + 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: - 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}行-请提供交接物料明细') + raise ParseError(f'第{ind+1}行-请提供交接物料明细') return instance class HandoverUpdateSerializer(CustomModelSerializer):