Merge branch 'master' of http://gitea.xxhhcty.xyz:8080/zcdsj/factory
This commit is contained in:
commit
c6ec4f6c56
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 3.2.12 on 2025-11-17 06:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('inm', '0037_alter_materialbatch_material'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='mioitem',
|
||||||
|
name='count_send',
|
||||||
|
field=models.DecimalField(blank=True, decimal_places=3, max_digits=12, null=True, verbose_name='发出数量'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -161,6 +161,7 @@ class MIOItem(BaseModel):
|
||||||
batch = models.TextField('批次号', db_index=True)
|
batch = models.TextField('批次号', db_index=True)
|
||||||
unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, null=True, blank=True)
|
unit_price = models.DecimalField('单价', max_digits=14, decimal_places=2, null=True, blank=True)
|
||||||
count = models.DecimalField('出入数量', max_digits=12, decimal_places=3)
|
count = models.DecimalField('出入数量', max_digits=12, decimal_places=3)
|
||||||
|
count_send = models.DecimalField('发出数量', max_digits=12, decimal_places=3, null=True, blank=True)
|
||||||
count_tested = models.PositiveIntegerField('已检数', null=True, blank=True)
|
count_tested = models.PositiveIntegerField('已检数', null=True, blank=True)
|
||||||
test_date = models.DateField('检验日期', null=True, blank=True)
|
test_date = models.DateField('检验日期', null=True, blank=True)
|
||||||
test_user = models.ForeignKey(
|
test_user = models.ForeignKey(
|
||||||
|
|
|
||||||
|
|
@ -160,9 +160,9 @@ def do_in(item: MIOItem):
|
||||||
for i in mias_list:
|
for i in mias_list:
|
||||||
material, batch, rate = i
|
material, batch, rate = i
|
||||||
new_count = rate * item.count # 假设 item.count 存在
|
new_count = rate * item.count # 假设 item.count 存在
|
||||||
action_list.append([material, batch, new_count, None])
|
action_list.append([material, batch, new_count, None, None])
|
||||||
else:
|
else:
|
||||||
action_list = [[item.material, item.batch, item.count, defect]]
|
action_list = [[item.material, item.batch, item.count, defect, item.wm]]
|
||||||
|
|
||||||
production_dept = None
|
production_dept = None
|
||||||
|
|
||||||
|
|
@ -170,12 +170,15 @@ def do_in(item: MIOItem):
|
||||||
if is_zhj:
|
if is_zhj:
|
||||||
xbatchs = [item.batch]
|
xbatchs = [item.batch]
|
||||||
for al in action_list:
|
for al in action_list:
|
||||||
xmaterial, xbatch, xcount, defect = al
|
xmaterial, xbatch, xcount, defect, xwm = al
|
||||||
if xcount <= 0:
|
if xcount <= 0:
|
||||||
raise ParseError("存在非正数!")
|
raise ParseError("存在非正数!")
|
||||||
|
|
||||||
xbatchs.append(xbatch)
|
xbatchs.append(xbatch)
|
||||||
if material.into_wm:
|
if material.into_wm:
|
||||||
|
if xwm:
|
||||||
|
wm = xwm
|
||||||
|
else:
|
||||||
wm_qs = WMaterial.objects.filter(
|
wm_qs = WMaterial.objects.filter(
|
||||||
batch=xbatch,
|
batch=xbatch,
|
||||||
material=xmaterial,
|
material=xmaterial,
|
||||||
|
|
@ -272,7 +275,7 @@ class InmService:
|
||||||
"""
|
"""
|
||||||
更新库存, 支持反向操作
|
更新库存, 支持反向操作
|
||||||
"""
|
"""
|
||||||
if not MIOItem.objects.filter(mio=instance).exists():
|
if is_reverse is False and not MIOItem.objects.filter(mio=instance).exists():
|
||||||
raise ParseError("出入库记录缺失明细,无法操作")
|
raise ParseError("出入库记录缺失明细,无法操作")
|
||||||
|
|
||||||
if instance.type == MIO.MIO_TYPE_PUR_IN: # 需要更新订单
|
if instance.type == MIO.MIO_TYPE_PUR_IN: # 需要更新订单
|
||||||
|
|
@ -347,8 +350,6 @@ class InmService:
|
||||||
out = -1
|
out = -1
|
||||||
"""
|
"""
|
||||||
mioitems = MIOItem.objects.filter(mio=instance)
|
mioitems = MIOItem.objects.filter(mio=instance)
|
||||||
if not mioitems.exists():
|
|
||||||
raise ParseError("未填写物料明细")
|
|
||||||
for i in mioitems:
|
for i in mioitems:
|
||||||
cls.update_mb_item(i, in_or_out, 'count')
|
cls.update_mb_item(i, in_or_out, 'count')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,19 +136,28 @@ def daoru_mioitems(path:str, mio:MIO):
|
||||||
|
|
||||||
mioitems = []
|
mioitems = []
|
||||||
ind = 2
|
ind = 2
|
||||||
while sheet[f"a{ind}"].value:
|
while sheet[f"a{ind}"].value or sheet[f"b{ind}"].value:
|
||||||
batch = sheet[f"b{ind}"].value
|
batch = sheet[f"e{ind}"].value
|
||||||
material_number = sheet[f"a{ind}"].value
|
material_number = sheet[f"a{ind}"].value
|
||||||
|
if material_number:
|
||||||
try:
|
try:
|
||||||
material = Material.objects.get(number=material_number)
|
material = Material.objects.get(number=material_number)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ParseError(f"未找到物料:{material_number} {e}")
|
raise ParseError(f"未找到物料:{material_number} {e}")
|
||||||
|
else:
|
||||||
|
material_name = sheet[f"b{ind}"].value
|
||||||
|
material_model = sheet[f"d{ind}"].value
|
||||||
|
material_specification = sheet[f"c{ind}"].value
|
||||||
|
try:
|
||||||
|
material = Material.objects.get(name=material_name, model=material_model, specification=material_specification)
|
||||||
|
except Exception as e:
|
||||||
|
raise ParseError(f"未找到物料:{material_name} {material_model} {material_specification} {e}")
|
||||||
if batch:
|
if batch:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
batch = "无"
|
batch = "无"
|
||||||
count = sheet[f"c{ind}"].value
|
count = sheet[f"f{ind}"].value
|
||||||
warehouse_name = sheet[f"d{ind}"].value
|
warehouse_name = sheet[f"g{ind}"].value
|
||||||
try:
|
try:
|
||||||
warehouse = WareHouse.objects.get(name=warehouse_name)
|
warehouse = WareHouse.objects.get(name=warehouse_name)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ from rest_framework.exceptions import ParseError
|
||||||
|
|
||||||
class MaterialFilter(filters.FilterSet):
|
class MaterialFilter(filters.FilterSet):
|
||||||
tag = filters.CharFilter(method='filter_tag', label="low_inm:库存不足")
|
tag = filters.CharFilter(method='filter_tag', label="low_inm:库存不足")
|
||||||
|
count__gt = filters.NumberFilter(field_name='count', lookup_expr='gt')
|
||||||
|
count_mb__gt = filters.NumberFilter(field_name='count_mb', lookup_expr='gt')
|
||||||
|
count_wm__gt = filters.NumberFilter(field_name='count_wm', lookup_expr='gt')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Material
|
model = Material
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@ class MaterialViewSet(CustomModelViewSet):
|
||||||
qs = super().get_queryset()
|
qs = super().get_queryset()
|
||||||
if self.action in ["list", "retrieve"]:
|
if self.action in ["list", "retrieve"]:
|
||||||
return qs.annotate(
|
return qs.annotate(
|
||||||
count_wm=Coalesce(
|
count_mb=Coalesce(
|
||||||
Sum('mb_m__count', filter=Q(mb_m__state=10)),
|
Sum('mb_m__count', filter=Q(mb_m__state=10)),
|
||||||
Value(0),
|
Value(0),
|
||||||
output_field=DecimalField()
|
output_field=DecimalField()
|
||||||
),
|
),
|
||||||
count_mb=Coalesce(
|
count_wm=Coalesce(
|
||||||
Sum('wm_m__count', filter=Q(wm_m__state=10)),
|
Sum('wm_m__count', filter=Q(wm_m__state=10)),
|
||||||
Value(0),
|
Value(0),
|
||||||
output_field=DecimalField()
|
output_field=DecimalField()
|
||||||
|
|
@ -62,7 +62,7 @@ class MaterialViewSet(CustomModelViewSet):
|
||||||
output_field=DecimalField()
|
output_field=DecimalField()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
return qs
|
||||||
|
|
||||||
def perform_destroy(self, instance):
|
def perform_destroy(self, instance):
|
||||||
from apps.inm.models import MaterialBatch
|
from apps.inm.models import MaterialBatch
|
||||||
|
|
|
||||||
|
|
@ -151,3 +151,4 @@ class SupplierAuditSerializer(CustomModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SupplierAudit
|
model = SupplierAudit
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
read_only_fields = EXCLUDE_FIELDS_BASE + ['ticket']
|
||||||
|
|
@ -11,7 +11,7 @@ from django.db import transaction
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from apps.pum.services import PumService
|
from apps.pum.services import PumService
|
||||||
from apps.wf.models import Ticket
|
from apps.wf.mixins import TicketMixin
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ class SupplierViewSet(CustomModelViewSet):
|
||||||
raise ParseError('该供应商存在采购订单不可删除')
|
raise ParseError('该供应商存在采购订单不可删除')
|
||||||
instance.delete()
|
instance.delete()
|
||||||
|
|
||||||
class SupplierAuditViewSet(CustomModelViewSet):
|
class SupplierAuditViewSet(TicketMixin, CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
list: 供应商审核
|
list: 供应商审核
|
||||||
|
|
||||||
|
|
@ -40,14 +40,7 @@ class SupplierAuditViewSet(CustomModelViewSet):
|
||||||
queryset = SupplierAudit.objects.all()
|
queryset = SupplierAudit.objects.all()
|
||||||
serializer_class = SupplierAuditSerializer
|
serializer_class = SupplierAuditSerializer
|
||||||
search_fields = ['name', 'material_name', 'material_cate']
|
search_fields = ['name', 'material_name', 'material_cate']
|
||||||
|
workflow_key = "wf_supplieraudit"
|
||||||
def perform_destroy(self, instance):
|
|
||||||
ticket:Ticket = instance.ticket
|
|
||||||
if ticket and ticket.state.type != 1:
|
|
||||||
raise ParseError('该记录关联的工单已被处理,不可删除')
|
|
||||||
instance.delete()
|
|
||||||
if ticket:
|
|
||||||
ticket.delete()
|
|
||||||
|
|
||||||
class PuPlanViewSet(CustomModelViewSet):
|
class PuPlanViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ def send_sms(phone: str, template_code: int, template_param: dict):
|
||||||
from aliyunsdkcore.request import CommonRequest
|
from aliyunsdkcore.request import CommonRequest
|
||||||
config = get_sysconfig()
|
config = get_sysconfig()
|
||||||
if config.get("sms", {}).get('enabled', False) is False:
|
if config.get("sms", {}).get('enabled', False) is False:
|
||||||
raise ParseError("短信发送功能未启用")
|
return False, {}
|
||||||
try:
|
try:
|
||||||
client = AcsClient(config['sms']['xn_key'],
|
client = AcsClient(config['sms']['xn_key'],
|
||||||
config['sms']['xn_secret'], 'default')
|
config['sms']['xn_secret'], 'default')
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
from apps.wf.models import Workflow, Ticket, State
|
from apps.wf.models import Workflow, Ticket, State
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
from apps.wf.services import WfService
|
from apps.wf.services import WfService
|
||||||
|
from apps.system.models import User
|
||||||
|
|
||||||
class TicketMixin:
|
class TicketMixin:
|
||||||
|
"""
|
||||||
|
可挂载到正常model,使其支持工作流
|
||||||
|
model添加ticket字段
|
||||||
|
serializer添加ticket_
|
||||||
|
该处会修改perform_create和perform_update方法,注意!
|
||||||
|
"""
|
||||||
workflow_key = None
|
workflow_key = None
|
||||||
ticket_auto_submit_on_update = True
|
ticket_auto_submit_on_update = True
|
||||||
ticket_data_save_keys = []
|
ticket_data_save_fields = []
|
||||||
|
|
||||||
def get_workflow_key(self, instance):
|
def get_workflow_key(self, instance):
|
||||||
return self.workflow_key
|
return self.workflow_key
|
||||||
|
|
@ -13,19 +20,58 @@ class TicketMixin:
|
||||||
def should_create_ticket(self, instance):
|
def should_create_ticket(self, instance):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def gen_ticket_data(self, instance):
|
||||||
|
ticket_data = {"t_model": instance.__class__.__name__, "t_id": instance.id}
|
||||||
|
if self.ticket_data_save_fields:
|
||||||
|
for field in self.ticket_data_save_fields:
|
||||||
|
if '.' in field:
|
||||||
|
attr_list = field.split('.')
|
||||||
|
expr = instance
|
||||||
|
for a in attr_list:
|
||||||
|
expr = getattr(expr, a)
|
||||||
|
ticket_data[field] = expr
|
||||||
|
else:
|
||||||
|
ticket_data[field] = getattr(instance, field)
|
||||||
|
return ticket_data
|
||||||
|
|
||||||
|
def perform_update(self, serializer):
|
||||||
|
ins = serializer.save()
|
||||||
|
if ins.ticket and self.ticket_auto_submit_on_update:
|
||||||
|
source_state:State = ins.ticket.state
|
||||||
|
if source_state.type != State.STATE_TYPE_START:
|
||||||
|
raise ParseError('该工单已开始流转,不可修改')
|
||||||
|
transition = WfService.get_state_transitions(source_state).first()
|
||||||
|
ticket_data = self.gen_ticket_data(ins)
|
||||||
|
WfService.handle_ticket(ticket=ins.ticket, transition=transition, new_ticket_data=ticket_data,
|
||||||
|
handler=self.request.user, oinfo=self.request.data)
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
ins = serializer.save()
|
ins = serializer.save()
|
||||||
if self.workflow_key:
|
handler:User = self.request.user
|
||||||
|
if self.should_create_ticket(ins):
|
||||||
|
workflow_key = self.get_workflow_key(ins)
|
||||||
|
if not workflow_key:
|
||||||
|
raise ParseError('工作流异常:必须赋值workflow_key')
|
||||||
try:
|
try:
|
||||||
wf = Workflow.objects.get(key=self.workflow_key)
|
wf = Workflow.objects.get(key=workflow_key)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ParseError(f'工作流{self.workflow_key}异常:{e}')
|
raise ParseError(f'工作流{workflow_key}异常:{e}')
|
||||||
|
|
||||||
|
# 开始创建工单
|
||||||
source_state: State = WfService.get_workflow_start_state(wf)
|
source_state: State = WfService.get_workflow_start_state(wf)
|
||||||
transitions = WfService.get_state_transitions(source_state)
|
transitions = WfService.get_state_transitions(source_state)
|
||||||
if transitions.count() == 1:
|
if transitions.count() == 1:
|
||||||
transition = transitions.first()
|
transition = transitions.first()
|
||||||
|
ticket_data = self.gen_ticket_data(ins)
|
||||||
|
WfService.handle_ticket(ticket=None, transition=transition, new_ticket_data=ticket_data,
|
||||||
|
handler=handler, oinfo=self.request.data)
|
||||||
else:
|
else:
|
||||||
raise ParseError(f'工作流{self.workflow_key}异常:起始状态{source_state}有多个后续状态;不可直接创建')
|
raise ParseError(f'工作流{workflow_key}异常:有多个后续状态;不可处理')
|
||||||
|
|
||||||
|
def perform_destroy(self, instance):
|
||||||
|
ticket = instance.ticket
|
||||||
|
if ticket and ticket.state.type != State.STATE_TYPE_START:
|
||||||
|
raise ParseError('该工单已开始流转,不可删除')
|
||||||
|
instance.delete()
|
||||||
|
ticket.delete()
|
||||||
|
|
||||||
|
|
@ -332,7 +332,10 @@ class WfService(object):
|
||||||
title_template = ticket.workflow.title_template
|
title_template = ticket.workflow.title_template
|
||||||
if title_template:
|
if title_template:
|
||||||
all_ticket_data = {**oinfo, **new_ticket_data}
|
all_ticket_data = {**oinfo, **new_ticket_data}
|
||||||
|
try:
|
||||||
ticket_title = title_template.format(**all_ticket_data)
|
ticket_title = title_template.format(**all_ticket_data)
|
||||||
|
except KeyError as e:
|
||||||
|
raise ParseError(f"工单标题模板中存在未定义的变量:{e}")
|
||||||
sn = WfService.get_ticket_sn(ticket.workflow) # 流水号
|
sn = WfService.get_ticket_sn(ticket.workflow) # 流水号
|
||||||
ticket.sn = sn
|
ticket.sn = sn
|
||||||
ticket.title = ticket_title
|
ticket.title = ticket_title
|
||||||
|
|
|
||||||
|
|
@ -1195,7 +1195,9 @@ class HandoverSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
if attrs["type"] == Handover.H_CHANGE:
|
if attrs["type"] == Handover.H_CHANGE:
|
||||||
attrs["mtype"] = Handover.H_MERGE
|
attrs["mtype"] = Handover.H_MERGE
|
||||||
if "material_changed" not in attrs:
|
if "material_changed" in attrs and attrs["material_changed"]:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
raise ParseError("必须指定改版后的物料")
|
raise ParseError("必须指定改版后的物料")
|
||||||
|
|
||||||
mtype = attrs["mtype"]
|
mtype = attrs["mtype"]
|
||||||
|
|
@ -1208,6 +1210,8 @@ class HandoverSerializer(CustomModelSerializer):
|
||||||
new_defect = new_wm.defect
|
new_defect = new_wm.defect
|
||||||
if not attrs.get("new_batch", None):
|
if not attrs.get("new_batch", None):
|
||||||
raise ParseError("必须指定合并后的批次")
|
raise ParseError("必须指定合并后的批次")
|
||||||
|
if 'undefined' in attrs['new_batch'] or 'null' in attrs['new_batch'] or '#' in attrs['new_batch']:
|
||||||
|
raise ParseError("新批次号含有不允许信息!")
|
||||||
|
|
||||||
|
|
||||||
wm:WMaterial = attrs.get('wm', None)
|
wm:WMaterial = attrs.get('wm', None)
|
||||||
|
|
@ -1548,3 +1552,8 @@ class MlogQuickSerializer(serializers.Serializer):
|
||||||
route = serializers.CharField(label="工艺步骤ID", required=False)
|
route = serializers.CharField(label="工艺步骤ID", required=False)
|
||||||
mtask = serializers.CharField(label="任务ID", required=False)
|
mtask = serializers.CharField(label="任务ID", required=False)
|
||||||
handle_user = serializers.CharField(label="操作人员ID")
|
handle_user = serializers.CharField(label="操作人员ID")
|
||||||
|
|
||||||
|
|
||||||
|
class BatchChangeSerializer(serializers.Serializer):
|
||||||
|
old_batch = serializers.CharField(label="原批号")
|
||||||
|
new_batch = serializers.CharField(label="新批号")
|
||||||
|
|
@ -49,6 +49,7 @@ from .serializers import (
|
||||||
MlogQuickSerializer,
|
MlogQuickSerializer,
|
||||||
MlogbwStartTestSerializer,
|
MlogbwStartTestSerializer,
|
||||||
HandoverListSerializer,
|
HandoverListSerializer,
|
||||||
|
BatchChangeSerializer
|
||||||
)
|
)
|
||||||
from .services import mlog_submit, handover_submit, mlog_revert, get_batch_dag, handover_revert
|
from .services import mlog_submit, handover_submit, mlog_revert, get_batch_dag, handover_revert
|
||||||
from apps.wpm.services import mlog_submit_validate, generate_new_batch
|
from apps.wpm.services import mlog_submit_validate, generate_new_batch
|
||||||
|
|
@ -203,6 +204,35 @@ class WMaterialViewSet(CustomListModelMixin, CustomGenericViewSet):
|
||||||
defect_ids = queryset.values_list("defect", flat=True).distinct()
|
defect_ids = queryset.values_list("defect", flat=True).distinct()
|
||||||
return Response(DefectSerializer(Defect.objects.filter(id__in=defect_ids), many=True).data)
|
return Response(DefectSerializer(Defect.objects.filter(id__in=defect_ids), many=True).data)
|
||||||
|
|
||||||
|
@action(methods=["post"], detail=False, perms_map={"post": "*"}, serializer_class=BatchChangeSerializer)
|
||||||
|
@transaction.atomic
|
||||||
|
def change_batch(self, request, *args, **kwargs):
|
||||||
|
"""修改批次号"""
|
||||||
|
sr = BatchChangeSerializer(data=request.data)
|
||||||
|
sr.is_valid(raise_exception=True)
|
||||||
|
vdata = sr.validated_data
|
||||||
|
new_batch = vdata["new_batch"]
|
||||||
|
old_batch = vdata["old_batch"]
|
||||||
|
if BatchSt.objects.filter(batch=new_batch).exists():
|
||||||
|
raise ParseError("新批次号已存在,不可使用")
|
||||||
|
from apps.cm.models import LableMat
|
||||||
|
from apps.inm.models import MIOItem, MaterialBatch, MaterialBatchA, MIOItemA
|
||||||
|
from apps.qm.models import FtestWork
|
||||||
|
LableMat.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
MIOItem.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
MIOItemA.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
MaterialBatch.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
MaterialBatchA.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
FtestWork.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
|
||||||
|
Mlog.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
Mlogb.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
WMaterial.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
Handover.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
Handoverb.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
Handover.objects.filter(new_batch=old_batch).update(new_batch=new_batch)
|
||||||
|
BatchSt.objects.filter(batch=old_batch).update(batch=new_batch)
|
||||||
|
return Response()
|
||||||
|
|
||||||
class MlogViewSet(CustomModelViewSet):
|
class MlogViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue