diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index b24c0ffc..4977214d 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -1107,6 +1107,9 @@ class MlogbOutUpdateSerializer(CustomModelSerializer): return ins def validate(self, attrs): + mlog: Mlog = attrs.get("mlog") + if mlog.submit_time is not None: + raise ParseError('生产日志已提交不可编辑') mlogbdefect = attrs.get("mlogbdefect", []) if mlogbdefect: attrs.pop("count_notok_json", None) diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 659fb340..201a75df 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -206,6 +206,13 @@ class MlogViewSet(CustomModelViewSet): data["oinfo_json_"] = {czx_dict.get(k, k): v for k, v in data.get("oinfo_json", {}).items()} return data + @classmethod + def lock_and_check_can_update(cls, mlog:Mlog): + mlog_lock:Mlog = Mlog.objects.select_for_update(id=mlog.id) + if mlog_lock.submit_time is not None: + raise ParseError("该记录已提交无法更改") + + def get_serializer_class(self): if self.request.query_params.get('with_mlogb', False): return MlogSerializer @@ -689,12 +696,13 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust def perform_destroy(self, instance): ins: Mlogb = instance - if ins.mlog.submit_time is not None: - raise ParseError('生产日志已提交不可编辑') + MlogViewSet.lock_and_check_can_update(ins.mlog) ins.delete() ins.mlog.cal_mlog_count_from_mlogb() def perform_update(self, serializer): + ins:Mlogb = serializer.instance + MlogViewSet.lock_and_check_can_update(ins.mlog) ins:Mlogb = serializer.save() ins.mlog.cal_mlog_count_from_mlogb() @@ -863,6 +871,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust def perform_create(self, serializer): mlogbin: Mlogb = serializer.save() + MlogViewSet.lock_and_check_can_update(mlogbin.mlog) MlogbInViewSet.p_create_after(mlogbin) @classmethod @@ -903,6 +912,8 @@ class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet): serializer_class = MlogbOutUpdateSerializer def perform_update(self, serializer): + ins:Mlogb = serializer.instance + MlogViewSet.lock_and_check_can_update(ins.mlog) material_out = serializer.validated_data.get('material_out') if material_out and material_out.tracking == Material.MA_TRACKING_SINGLE: raise ParseError("单件产品不支持直接修改") @@ -968,12 +979,16 @@ class MlogbwViewSet(CustomModelViewSet): insx = ins else: insx = [ins] + checked = False for ins in insx: if mlog is None: mlog = ins.mlogb.mlog else: if mlog != ins.mlogb.mlog: raise ParseError("所有记录必须属于同一张日志") + if not checked: + MlogViewSet.lock_and_check_can_update(mlog) + checked = True wpr:Wpr = ins.wpr mlogb:Mlogb = ins.mlogb if wpr.wm != mlogb.wm_in: @@ -1041,20 +1056,25 @@ class MlogbwViewSet(CustomModelViewSet): if isinstance(mlogbw, list): pass else: - Mlogbw.cal_count_notok(mlogbw.mlogb) mlog = mlogbw.mlogb.mlog + MlogViewSet.lock_and_check_can_update(mlog) + Mlogbw.cal_count_notok(mlogbw.mlogb) + mlog.cal_mlog_count_from_mlogb() def after_bulk_update(self, objs): mlogbIds = list(set([obj["mlogb"] for obj in objs])) for mlogbId in mlogbIds: mlogb = Mlogb.objects.get(id=mlogbId) - Mlogbw.cal_count_notok(mlogb) mlog = mlogb.mlog + MlogViewSet.lock_and_check_can_update(mlog) + Mlogbw.cal_count_notok(mlogb) + mlog.cal_mlog_count_from_mlogb() def perform_destroy(self, instance:Mlogbw): mlogb:Mlogb = instance.mlogb + MlogViewSet.lock_and_check_can_update(mlogb.mlog) if mlogb.material_out is not None and instance.wpr is not None: raise ParseError("不能删除该产出明细") @@ -1105,8 +1125,7 @@ class MlogUserViewSet(BulkCreateModelMixin, ListModelMixin, DestroyModelMixin, C def perform_destroy(self, instance): mlog:Mlog = instance.mlog - if mlog.submit_time is not None: - raise ParseError("不能删除该记录") + MlogViewSet.lock_and_check_can_update(mlog) return super().perform_destroy(instance)