556 lines
21 KiB
Python
556 lines
21 KiB
Python
from django.shortcuts import render
|
||
from rest_framework.mixins import ListModelMixin, DestroyModelMixin
|
||
from rest_framework.exceptions import ParseError, PermissionDenied
|
||
from rest_framework.decorators import action
|
||
from django.db import transaction
|
||
from django.conf import settings
|
||
from rest_framework import serializers
|
||
from django.utils import timezone
|
||
from rest_framework.response import Response
|
||
from django.db.models import Sum
|
||
|
||
from apps.inm.models import WareHouse, MaterialBatch, MIO, MIOItem, MIOItemw, Pack
|
||
from apps.inm.serializers import (
|
||
MaterialBatchSerializer, WareHourseSerializer, MIOListSerializer, MIOItemSerializer, MioItemAnaSerializer,
|
||
MIODoSerializer, MIOSaleSerializer, MIOPurSerializer, MIOOtherSerializer, MIOItemCreateSerializer,
|
||
MaterialBatchDetailSerializer, MIODetailSerializer, MIOItemTestSerializer, MIOItemPurInTestSerializer,
|
||
MIOItemwSerializer, MioItemDetailSerializer, PackSerializer, PackMioSerializer, MIOItemListSimpleSerializer)
|
||
from apps.inm.serializers2 import MIOItemwCreateUpdateSerializer
|
||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||
from apps.inm.services import InmService
|
||
from apps.inm.services_daoru import daoru_mb, daoru_mioitem_test, daoru_mioitems
|
||
from apps.utils.mixins import (BulkCreateModelMixin, BulkDestroyModelMixin, BulkUpdateModelMixin,
|
||
CustomListModelMixin)
|
||
from apps.utils.permission import has_perm
|
||
from .filters import MaterialBatchFilter, MioFilter
|
||
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
|
||
from datetime import datetime
|
||
|
||
|
||
# Create your views here.
|
||
class WarehouseVIewSet(CustomModelViewSet):
|
||
"""
|
||
list: 仓库信息
|
||
|
||
仓库信息
|
||
"""
|
||
queryset = WareHouse.objects.all()
|
||
serializer_class = WareHourseSerializer
|
||
search_fields = ['name', 'number', 'place']
|
||
ordering = ['create_time']
|
||
|
||
def perform_destroy(self, instance):
|
||
if MaterialBatch.objects.filter(warehouse=instance).exclude(count=0).exists():
|
||
raise ParseError('该仓库存在物料')
|
||
instance.delete()
|
||
|
||
|
||
class MaterialBatchViewSet(ListModelMixin, CustomGenericViewSet):
|
||
"""
|
||
list: 物料批次
|
||
|
||
物料批次
|
||
"""
|
||
perms_map = {'get': '*'}
|
||
queryset = MaterialBatch.objects.filter(count__gt=0)
|
||
serializer_class = MaterialBatchSerializer
|
||
retrieve_serializer_class = MaterialBatchDetailSerializer
|
||
select_related_fields = ['warehouse', 'material', 'supplier']
|
||
filterset_class = MaterialBatchFilter
|
||
search_fields = ['material__name', 'material__number',
|
||
'material__model', 'material__specification', 'batch']
|
||
ordering = ['-update_time']
|
||
|
||
@action(methods=['post'], detail=False, serializer_class=serializers.Serializer, perms_map={'post': 'materialbatch.daoru'})
|
||
@transaction.atomic
|
||
def daoru(self, request, *args, **kwargs):
|
||
"""导入物料批次
|
||
|
||
导入物料
|
||
"""
|
||
daoru_mb(settings.BASE_DIR + request.data.get('path', ''))
|
||
return Response()
|
||
|
||
|
||
class MioDoViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, CustomGenericViewSet):
|
||
perms_map = {'post': '*', 'put': 'mio.do'}
|
||
queryset = MIO.objects.filter(
|
||
type__in=[MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_DO_OUT])
|
||
serializer_class = MIODoSerializer
|
||
|
||
def create(self, request, *args, **kwargs):
|
||
"""
|
||
生产领料/入库
|
||
|
||
生产领料/入库
|
||
"""
|
||
return super().create(request, *args, **kwargs)
|
||
|
||
|
||
class MioSaleViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, CustomGenericViewSet):
|
||
perms_map = {'post': '*', 'put': 'mio.sale'}
|
||
queryset = MIO.objects.filter(
|
||
type__in=[MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_DO_OUT])
|
||
serializer_class = MIOSaleSerializer
|
||
|
||
def create(self, request, *args, **kwargs):
|
||
"""
|
||
销售出库
|
||
|
||
销售出库
|
||
"""
|
||
return super().create(request, *args, **kwargs)
|
||
|
||
|
||
class MioPurViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, CustomGenericViewSet):
|
||
perms_map = {'post': '*', 'put': 'mio.pur'}
|
||
queryset = MIO.objects.filter(
|
||
type__in=[MIO.MIO_TYPE_PUR_IN])
|
||
serializer_class = MIOPurSerializer
|
||
|
||
def create(self, request, *args, **kwargs):
|
||
"""
|
||
采购入库
|
||
|
||
采购入库
|
||
"""
|
||
return super().create(request, *args, **kwargs)
|
||
|
||
|
||
class MioOtherViewSet(BulkCreateModelMixin, BulkUpdateModelMixin, CustomGenericViewSet):
|
||
perms_map = {'post': '*', 'put': 'mio.other'}
|
||
queryset = MIO.objects.filter(
|
||
type__in=[MIO.MIO_TYPE_OTHER_OUT, MIO.MIO_TYPE_OTHER_IN])
|
||
serializer_class = MIOOtherSerializer
|
||
|
||
def create(self, request, *args, **kwargs):
|
||
"""
|
||
其他出入库
|
||
|
||
其他出入库
|
||
"""
|
||
return super().create(request, *args, **kwargs)
|
||
|
||
|
||
class MIOViewSet(CustomModelViewSet):
|
||
"""
|
||
list: 出入库记录
|
||
|
||
出入库记录
|
||
"""
|
||
queryset = MIO.objects.all()
|
||
select_related_fields = ['create_by', 'belong_dept', 'do_user',
|
||
'submit_user', 'supplier', 'order', 'customer', 'pu_order', 'mgroup']
|
||
prefetch_related_fields = ['materials']
|
||
serializer_class = MIOListSerializer
|
||
retrieve_serializer_class = MIODetailSerializer
|
||
filterset_class = MioFilter
|
||
search_fields = ['id', 'number', 'item_mio__batch', 'item_mio__material__name', 'item_mio__material__specification', 'item_mio__material__model',
|
||
'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):
|
||
# 1. 收集所有mio的ID
|
||
mio_ids = [item['id'] for item in data]
|
||
|
||
# 2. 预初始化mio字典和items列表
|
||
mio_dict = {item['id']: {
|
||
**item,
|
||
'is_tested': False, # 默认值设为False
|
||
'mioitems': []
|
||
} for item in data}
|
||
|
||
# 3. 批量查询MIOItem数据
|
||
if mio_ids: # 避免空查询
|
||
mioitems = MIOItemListSimpleSerializer(
|
||
instance=MIOItem.objects.filter(
|
||
mio__id__in=mio_ids
|
||
).select_related("warehouse", "material"),
|
||
many=True
|
||
).data
|
||
|
||
# 4. 单次循环处理所有item
|
||
for item in mioitems:
|
||
mio_id = item['mio']
|
||
if mio_id in mio_dict:
|
||
mio_dict[mio_id]['mioitems'].append(item)
|
||
# 更新is_tested状态(只要有一个item有test_date就为True)
|
||
if item.get('test_date'):
|
||
mio_dict[mio_id]['is_tested'] = True
|
||
|
||
# 5. 直接返回原始data列表,避免额外转换
|
||
for item in data:
|
||
item.update(mio_dict[item['id']])
|
||
|
||
return data
|
||
|
||
def get_serializer_class(self):
|
||
if self.action in ['create', 'update', 'partial_update']:
|
||
type = self.request.data.get('type')
|
||
user = self.request.user
|
||
if type in [MIO.MIO_TYPE_DO_IN, MIO.MIO_TYPE_DO_OUT, MIO.MIO_TYPE_BORROW_OUT, MIO.MIO_TYPE_RETURN_IN]:
|
||
if not has_perm(user, ['mio.do']):
|
||
raise PermissionDenied
|
||
return MIODoSerializer
|
||
elif type in [MIO.MIO_TYPE_OTHER_IN, MIO.MIO_TYPE_OTHER_OUT]:
|
||
if not has_perm(user, ['mio.other']):
|
||
raise PermissionDenied
|
||
return MIOOtherSerializer
|
||
elif type == MIO.MIO_TYPE_SALE_OUT:
|
||
if not has_perm(user, ['mio.sale']):
|
||
raise PermissionDenied
|
||
return MIOSaleSerializer
|
||
elif type in [MIO.MIO_TYPE_PUR_IN, MIO.MIO_TYPE_PUR_OUT]:
|
||
if not has_perm(user, ['mio.pur']):
|
||
raise PermissionDenied
|
||
return MIOPurSerializer
|
||
return super().get_serializer_class()
|
||
|
||
def perform_destroy(self, instance):
|
||
if instance.state != MIO.MIO_CREATE:
|
||
raise ParseError('非创建中不可删除')
|
||
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:MIO = self.get_object()
|
||
if ins.inout_date is None:
|
||
raise ParseError('出入库日期未填写')
|
||
if ins.state != MIO.MIO_CREATE:
|
||
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)
|
||
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):
|
||
"""撤回
|
||
|
||
撤回
|
||
"""
|
||
ins = self.get_object()
|
||
user = self.request.user
|
||
if ins.state != MIO.MIO_SUBMITED:
|
||
raise ParseError('记录状态异常')
|
||
if ins.submit_user != user:
|
||
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)
|
||
return Response()
|
||
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.update'}, serializer_class=PackMioSerializer)
|
||
@transaction.atomic
|
||
def pack_mioitem(self, request, *args, **kwargs):
|
||
"""装箱
|
||
|
||
装箱
|
||
"""
|
||
mio:MIO = self.get_object()
|
||
if mio.submit_time is not None:
|
||
raise ParseError('该出入库已提交不可装箱')
|
||
sr = PackMioSerializer(data=request.data)
|
||
sr.is_valid(raise_exception=True)
|
||
vdata = sr.validated_data
|
||
pack_index = vdata["pack_index"]
|
||
mioitems = vdata["mioitems"]
|
||
if not mioitems:
|
||
raise ParseError('未选择明细')
|
||
for id in mioitems:
|
||
mioitem = MIOItem.objects.get(id=id)
|
||
if mioitem.mio != mio:
|
||
raise ParseError('存在明细不属于该箱')
|
||
mioitem.pack_index = pack_index
|
||
mioitem.save(update_fields=['pack_index', 'update_time'])
|
||
return Response()
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.update'}, serializer_class=serializers.Serializer)
|
||
def daoru_mioitem(self, request, *args, **kwargs):
|
||
"""导入明细
|
||
|
||
导入明细
|
||
"""
|
||
daoru_mioitems(settings.BASE_DIR + request.data.get('path', ''), mio=self.get_object())
|
||
return Response()
|
||
class PackViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||
"""
|
||
list: 装箱记录
|
||
|
||
装箱记录
|
||
"""
|
||
perms_map = {'get': '*', 'post': '*', 'delete': '*'}
|
||
queryset = Pack.objects.all()
|
||
serializer_class = PackSerializer
|
||
filterset_fields = ["mio"]
|
||
ordering = ["mio", "index"]
|
||
|
||
@action(methods=['post'], detail=False, perms_map={'post': 'mio.update'}, serializer_class=PackMioSerializer)
|
||
@transaction.atomic
|
||
def pack_mioitem(self, request, *args, **kwargs):
|
||
"""装箱
|
||
|
||
装箱
|
||
"""
|
||
vdata = PackMioSerializer(data=request.data)
|
||
packId = vdata["pack"]
|
||
pack:Pack = Pack.objects.get(id=packId)
|
||
mioitems = vdata["mioitems"]
|
||
if not mioitems:
|
||
raise ParseError('未选择明细')
|
||
for id in mioitems:
|
||
mioitem = MIOItem.objects.get(id=id)
|
||
if mioitem.mio != pack.mio:
|
||
raise ParseError('存在明细不属于该装箱记录')
|
||
mioitem.pack = pack
|
||
mioitem.save(update_fields=['pack', 'update_time'])
|
||
return Response()
|
||
|
||
|
||
|
||
class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||
"""
|
||
list: 出入库明细
|
||
|
||
出入库明细
|
||
"""
|
||
perms_map = {'get': '*', 'post': '*', 'delete': '*'}
|
||
queryset = MIOItem.objects.all()
|
||
serializer_class = MIOItemSerializer
|
||
retrieve_serializer_class = MioItemDetailSerializer
|
||
create_serializer_class = MIOItemCreateSerializer
|
||
select_related_fields = ['warehouse', 'mio', 'material', 'test_user']
|
||
filterset_fields = {
|
||
"warehouse": ["exact"],
|
||
"mio": ["exact"],
|
||
"mio__state": ["exact"],
|
||
"mio__type": ["exact", "in"],
|
||
"mio__inout_date": ["gte", "lte", "exact"],
|
||
"material": ["exact"],
|
||
"material__type": ["exact"],
|
||
"test_date": ["isnull", "exact"]
|
||
}
|
||
ordering = ['create_time']
|
||
ordering_fields = ['create_time', 'test_date']
|
||
search_fields =['batch', 'a_mioitem__batch']
|
||
|
||
def add_info_for_list(self, data):
|
||
with_mio = self.request.query_params.get('with_mio', "no")
|
||
if with_mio == "yes" and isinstance(data, list):
|
||
mio_ids = [item['mio'] for item in data]
|
||
mio_qs = MIO.objects.filter(id__in=mio_ids)
|
||
mio_qs_= MIOListSerializer(mio_qs, many=True).data
|
||
mio_dict = {mio['id']: mio for mio in mio_qs_}
|
||
for item in data:
|
||
mioId = item['mio']
|
||
item['mio_'] = mio_dict[mioId]
|
||
return data
|
||
|
||
@swagger_auto_schema(manual_parameters=[
|
||
openapi.Parameter(name="with_mio", in_=openapi.IN_QUERY, description="是否返回出入库记录信息",
|
||
type=openapi.TYPE_STRING, required=False),
|
||
openapi.Parameter(name="query", in_=openapi.IN_QUERY, description="定制返回数据",
|
||
type=openapi.TYPE_STRING, required=False),
|
||
openapi.Parameter(name="with_children", in_=openapi.IN_QUERY, description="带有children(yes/no/count)",
|
||
type=openapi.TYPE_STRING, required=False)
|
||
])
|
||
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):
|
||
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)
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.update'}, serializer_class=serializers.Serializer)
|
||
@transaction.atomic
|
||
def revert_and_del(self, request, *args, **kwargs):
|
||
"""撤回并删除
|
||
|
||
撤回并删除
|
||
"""
|
||
ins:MIOItem = self.get_object()
|
||
InmService.revert_and_del(ins)
|
||
return Response()
|
||
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=MIOItemTestSerializer)
|
||
@transaction.atomic
|
||
def test(self, request, *args, **kwargs):
|
||
"""半成品检验
|
||
|
||
半成品检验
|
||
"""
|
||
ins: MIOItem = self.get_object()
|
||
if ins.material.tracking != Material.MA_TRACKING_BATCH:
|
||
raise ParseError('该物料非批次管理')
|
||
mio = ins.mio
|
||
if ins.test_date:
|
||
raise ParseError('该明细已检验')
|
||
if mio.state != MIO.MIO_SUBMITED:
|
||
raise ParseError('该出入库记录还未提交')
|
||
sr = MIOItemTestSerializer(instance=ins, data=request.data)
|
||
sr.is_valid(raise_exception=True)
|
||
sr.save()
|
||
# 开始变动库存
|
||
InmService.update_mb_item(ins, -1, 'count_notok')
|
||
return Response()
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=serializers.Serializer)
|
||
@transaction.atomic
|
||
def test_revert(self, request, *args, **kwargs):
|
||
"""
|
||
检验撤回
|
||
"""
|
||
ins: MIOItem = self.get_object()
|
||
if ins.test_date is None:
|
||
raise ParseError('该明细还未检验')
|
||
if ins.count_notok > 0:
|
||
InmService.update_mb_item(ins, 1, 'count_notok')
|
||
elif ins.count_notok == 0:
|
||
pass
|
||
ins.test_date = None
|
||
ins.save()
|
||
return Response()
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=MIOItemPurInTestSerializer)
|
||
@transaction.atomic
|
||
def test_pur_in(self, request, *args, **kwargs):
|
||
"""入厂检验
|
||
|
||
入厂检验
|
||
"""
|
||
ins: MIOItem = self.get_object()
|
||
if ins.material.tracking != Material.MA_TRACKING_BATCH:
|
||
raise ParseError('该物料非批次管理')
|
||
if ins.test_date:
|
||
raise ParseError('该明细已检验')
|
||
sr = MIOItemPurInTestSerializer(instance=ins, data=request.data)
|
||
sr.is_valid(raise_exception=True)
|
||
sr.save()
|
||
return Response()
|
||
|
||
@action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MioItemAnaSerializer)
|
||
def sale_out_ana(self, request, *args, **kwargs):
|
||
"""交付统计数据
|
||
|
||
交付统计数据
|
||
"""
|
||
sr = MIOItemTestSerializer(data=request.data)
|
||
sr.is_valid(raise_exception=True)
|
||
vdata = sr.validated_data
|
||
mioitems = MIOItem.objects.filter(
|
||
mio__type='sale_out', mio__state=MIO.MIO_SUBMITED)
|
||
if vdata.get('material_cate'):
|
||
mioitems = mioitems.filter(
|
||
material__cate=vdata['material_cate'])
|
||
if vdata.get('start_date', ''):
|
||
mioitems = mioitems.filter(
|
||
mio__inout_date__gte=vdata['start_date'])
|
||
if vdata.get('end_date', ''):
|
||
mioitems = mioitems.filter(mio__inout_date__lte=vdata['end_date'])
|
||
res = mioitems.aggregate(count=Sum('count'))
|
||
for i in res:
|
||
if res[i] is None:
|
||
res[i] = 0
|
||
return Response(res)
|
||
|
||
@action(methods=['post'], detail=True, perms_map={'post': 'mio.update'}, serializer_class=serializers.Serializer)
|
||
@transaction.atomic
|
||
def test_daoru_bg(self, request, *args, **kwargs):
|
||
"""导入棒管检验
|
||
|
||
导入棒管检验
|
||
"""
|
||
daoru_mioitem_test(path=settings.BASE_DIR + request.data.get('path', ''), mioitem=self.get_object())
|
||
return Response()
|
||
|
||
|
||
class MIOItemwViewSet(CustomModelViewSet):
|
||
perms_map = {'get': '*', 'post': 'mio.update', 'put': 'mio.update', 'delete': 'mio.update'}
|
||
queryset = MIOItemw.objects.all()
|
||
serializer_class = MIOItemwCreateUpdateSerializer
|
||
filterset_fields = {
|
||
'mioitem': ['exact'],
|
||
'mioitem__material__type': ['exact'],
|
||
"wpr": ['exact'],
|
||
"number": ["exact"],
|
||
"ftest": ["isnull"],
|
||
"mioitem__mio__state": ["exact"]
|
||
}
|
||
select_related_fields = ["ftest"]
|
||
ordering = ["number", "create_time"]
|
||
ordering_fields = ["number", "create_time"]
|
||
|
||
def filter_queryset(self, queryset):
|
||
if not self.detail:
|
||
if not self.request.query_params.get('mioitem', None):
|
||
if "ftest__isnull" in self.request.query_params:
|
||
pass
|
||
else:
|
||
raise ParseError('请指定所属出入库记录明细')
|
||
return super().filter_queryset(queryset)
|
||
|
||
def cal_mioitem_count(self, mioitem:MIOItem):
|
||
count = MIOItemw.objects.filter(mioitem=mioitem).count()
|
||
mioitem.count = count
|
||
mioitem.count_tested = MIOItemw.objects.filter(mioitem=mioitem, ftest__isnull=False).count()
|
||
mioitem.count_notok = MIOItemw.objects.filter(mioitem=mioitem, ftest__is_ok=False).count()
|
||
if mioitem.test_date is None:
|
||
mioitem.test_date = datetime.now()
|
||
if mioitem.test_user is None:
|
||
mioitem.test_user = self.request.user
|
||
mioitem.save()
|
||
|
||
def perform_create(self, serializer):
|
||
MIOViewSet.lock_and_check_can_update(serializer.validated_data['mioitem'].mio)
|
||
ins:MIOItemw = serializer.save()
|
||
self.cal_mioitem_count(ins.mioitem)
|
||
|
||
def perform_update(self, serializer):
|
||
ins:MIOItemw = serializer.instance
|
||
MIOViewSet.lock_and_check_can_update(ins.mioitem.mio)
|
||
ins:MIOItemw = serializer.save()
|
||
self.cal_mioitem_count(ins.mioitem)
|
||
|
||
def perform_destroy(self, instance: MIOItemw):
|
||
mioitem = instance.mioitem
|
||
MIOViewSet.lock_and_check_can_update(mioitem.mio)
|
||
ftest = instance.ftest
|
||
instance.delete()
|
||
if ftest:
|
||
ftest.delete()
|
||
self.cal_mioitem_count(mioitem)
|
||
|