feat: utask支持恢复任务/排产支持传入to_day
This commit is contained in:
parent
643efa448e
commit
d766d880e7
|
@ -3,7 +3,7 @@ from rest_framework.exceptions import ValidationError, ParseError
|
|||
import math
|
||||
|
||||
from apps.mtm.serializers import MaterialSimpleSerializer
|
||||
from apps.pm.models import Mtask, Utask
|
||||
from apps.pm.models import Mtask, Utask, SCHEDULE_TYPE
|
||||
from apps.sam.models import OrderItem
|
||||
from apps.utils.serializers import CustomModelSerializer
|
||||
from apps.system.models import Dept
|
||||
|
@ -80,6 +80,15 @@ class MtaskSerializer(CustomModelSerializer):
|
|||
'number', 'count', 'start_date', 'end_date']}
|
||||
return super().update(instance, new_data)
|
||||
|
||||
class SchedueMtasksSerializer(serializers.Serializer):
|
||||
ids = serializers.ListField(
|
||||
child=serializers.CharField(max_length=20), label="utask ID列表")
|
||||
schedule_type = serializers.ChoiceField(label='排产类型', choices=SCHEDULE_TYPE, required=False)
|
||||
|
||||
def validate(self, attrs):
|
||||
if "schedule_type" not in attrs:
|
||||
attrs["schedule_type"] = "to_day"
|
||||
return super().validate(attrs)
|
||||
|
||||
class SchedueSerializer(serializers.Serializer):
|
||||
orderitems = serializers.PrimaryKeyRelatedField(
|
||||
|
|
|
@ -53,9 +53,10 @@ class PmService:
|
|||
OrderItem.objects.filter(id__in=orderitemIds).update(utask=utask)
|
||||
|
||||
@classmethod
|
||||
def schedue_mtasks(cls, user, utask: Utask):
|
||||
def schedue_mtasks(cls, user, utask: Utask, schedule_type: str = "to_day"):
|
||||
"""
|
||||
从大任务自动排产出小任务
|
||||
param schedule_type: to_day/to_mgroup
|
||||
从大任务自动排产出小任务(按工段/按天分配)
|
||||
"""
|
||||
# from apps.wpm.services import make_sflogs
|
||||
if utask.state != Utask.UTASK_CREATED:
|
||||
|
@ -66,27 +67,42 @@ class PmService:
|
|||
# 计算相差天数
|
||||
rela_days = (end_date - start_date).days + 1
|
||||
if utask.mgroup: # 如果存在指定的mgroup则直接排产
|
||||
if rela_days >= 1:
|
||||
task_count_day = math.ceil(count/rela_days)
|
||||
for i in range(rela_days):
|
||||
task_date = start_date + timedelta(days=i)
|
||||
Mtask.objects.create(**{
|
||||
'type': utask.type,
|
||||
'number': f'{number}_{i+1}',
|
||||
'material_out': utask.material,
|
||||
'material_in': utask.material_in,
|
||||
'mgroup': utask.mgroup,
|
||||
'count': task_count_day,
|
||||
'start_date': task_date,
|
||||
'end_date': task_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'is_count_utask': True
|
||||
})
|
||||
# 先撤销有需要再加
|
||||
# make_sflogs(mgroup=utask.mgroup,
|
||||
# start_date=task_date, end_date=task_date, create_by=user)
|
||||
if schedule_type == 'to_day':
|
||||
if rela_days >= 1:
|
||||
task_count_day = math.ceil(count/rela_days)
|
||||
for i in range(rela_days):
|
||||
task_date = start_date + timedelta(days=i)
|
||||
Mtask.objects.create(**{
|
||||
'type': utask.type,
|
||||
'number': f'{number}_{i+1}',
|
||||
'material_out': utask.material,
|
||||
'material_in': utask.material_in,
|
||||
'mgroup': utask.mgroup,
|
||||
'count': task_count_day,
|
||||
'start_date': task_date,
|
||||
'end_date': task_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'is_count_utask': True
|
||||
})
|
||||
elif schedule_type == 'to_mgroup':
|
||||
Mtask.objects.create(**{
|
||||
'type': utask.type,
|
||||
'number': f'{number}_r1',
|
||||
'material_out': product,
|
||||
'material_in': utask.material_in,
|
||||
'mgroup': utask.mgroup,
|
||||
'count': count,
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'is_count_utask': True
|
||||
})
|
||||
else:
|
||||
raise ParseError('不支持的排产类型')
|
||||
else:
|
||||
# 获取产品的加工路线
|
||||
rqs = Route.get_routes(product)
|
||||
|
@ -112,35 +128,50 @@ class PmService:
|
|||
raise ParseError(f'第{ind+1}步-工段不存在!')
|
||||
else: # 后面可能会指定车间
|
||||
raise ParseError(f'第{ind+1}步-工段存在多个!')
|
||||
task_count = count
|
||||
if val.out_rate:
|
||||
if val.out_rate > 1:
|
||||
task_count = math.ceil(
|
||||
count / (val.out_rate/100))
|
||||
else:
|
||||
task_count = math.ceil(count / val.out_rate)
|
||||
task_count_day = math.ceil(task_count/rela_days)
|
||||
if rela_days >= 1:
|
||||
for i in range(rela_days):
|
||||
task_date = start_date + timedelta(days=i)
|
||||
Mtask.objects.create(**{
|
||||
'number': f'{number}_r{ind+1}_{i+1}',
|
||||
'type': utask.type,
|
||||
'material_out': halfgood,
|
||||
'material_in': material_in,
|
||||
'mgroup': mgroup,
|
||||
'count': task_count_day,
|
||||
'start_date': task_date,
|
||||
'end_date': task_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'is_count_utask': val.is_count_utask
|
||||
})
|
||||
# 先撤销,有需要再加
|
||||
# make_sflogs(mgroup=mgroup,
|
||||
# start_date=task_date, end_date=task_date, create_by=user)
|
||||
|
||||
if schedule_type == 'to_day':
|
||||
task_count = count
|
||||
if val.out_rate:
|
||||
if val.out_rate > 1:
|
||||
task_count = math.ceil(
|
||||
count / (val.out_rate/100))
|
||||
else:
|
||||
task_count = math.ceil(count / val.out_rate)
|
||||
task_count_day = math.ceil(task_count/rela_days)
|
||||
if rela_days >= 1:
|
||||
for i in range(rela_days):
|
||||
task_date = start_date + timedelta(days=i)
|
||||
Mtask.objects.create(**{
|
||||
'number': f'{number}_r{ind+1}_{i+1}',
|
||||
'type': utask.type,
|
||||
'material_out': halfgood,
|
||||
'material_in': material_in,
|
||||
'mgroup': mgroup,
|
||||
'count': task_count_day,
|
||||
'start_date': task_date,
|
||||
'end_date': task_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'is_count_utask': val.is_count_utask
|
||||
})
|
||||
elif schedule_type == 'to_mgroup':
|
||||
Mtask.objects.create(**{
|
||||
'number': f'{number}_r{ind+1}',
|
||||
'type': utask.type,
|
||||
'material_out': halfgood,
|
||||
'material_in': material_in,
|
||||
'mgroup': mgroup,
|
||||
'count': count,
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
'utask': utask,
|
||||
'create_by': user,
|
||||
'update_by': user,
|
||||
'hour_work': val.hour_work,
|
||||
'is_count_utask': val.is_count_utask
|
||||
})
|
||||
else:
|
||||
raise ParseError('不支持的排产类型')
|
||||
@classmethod
|
||||
def check_orderitems(cls, orderitems: QuerySet[OrderItem]):
|
||||
"""
|
||||
|
|
|
@ -9,7 +9,8 @@ from apps.utils.viewsets import CustomModelViewSet
|
|||
|
||||
from .filters import MtaskFilter, UtaskFilter
|
||||
from .models import Mtask, Utask
|
||||
from .serializers import MtaskSerializer, SchedueSerializer, UtaskSerializer, MtaskDaySerializer, MtaskAddInfoSerializer
|
||||
from .serializers import (MtaskSerializer, SchedueSerializer, UtaskSerializer,
|
||||
MtaskDaySerializer, MtaskAddInfoSerializer, SchedueMtasksSerializer)
|
||||
from .services import PmService
|
||||
from django.utils import timezone
|
||||
|
||||
|
@ -33,12 +34,12 @@ class UtaskViewSet(CustomModelViewSet):
|
|||
raise ParseError('该任务状态不可删除')
|
||||
return super().perform_destroy(instance)
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'utask.stop'}, serializer_class=Serializer)
|
||||
@action(methods=['post'], detail=True, perms_map={'post': 'utask.toggle'}, serializer_class=Serializer)
|
||||
@transaction.atomic
|
||||
def stop(self, request, *args, **kwargs):
|
||||
"""停止任务
|
||||
def toggle(self, request, *args, **kwargs):
|
||||
"""停止/恢复任务
|
||||
|
||||
停止任务
|
||||
停止/恢复任务
|
||||
"""
|
||||
obj = self.get_object()
|
||||
user = request.user
|
||||
|
@ -51,8 +52,16 @@ class UtaskViewSet(CustomModelViewSet):
|
|||
# 停止所有小任务
|
||||
Mtask.objects.filter(
|
||||
utask=obj, state=Mtask.MTASK_ASSGINED).update(state=Mtask.MTASK_STOP, update_by=user, update_time=now)
|
||||
elif obj.state == Utask.UTASK_STOP:
|
||||
obj.state = Utask.UTASK_WORKING
|
||||
obj.update_by = user
|
||||
obj.update_time = now
|
||||
obj.save()
|
||||
# 恢复所有小任务
|
||||
Mtask.objects.filter(
|
||||
utask=obj, state=Mtask.MTASK_STOP).update(state=Mtask.MTASK_ASSGINED, update_by=user, update_time=now)
|
||||
else:
|
||||
raise ParseError('该状态下不可停止')
|
||||
raise ParseError('该状态下不可变更')
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'utask.schedue'}, serializer_class=SchedueSerializer)
|
||||
|
@ -69,10 +78,10 @@ class UtaskViewSet(CustomModelViewSet):
|
|||
request.data['orderitems'], vdata['start_date'], vdata['end_date'], vdata.get('belong_dept', None))
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'utask.schedue'}, serializer_class=PkSerializer)
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'utask.schedue'}, serializer_class=SchedueMtasksSerializer)
|
||||
@transaction.atomic
|
||||
def schedue_mtasks(self, request, *args, **kwargs):
|
||||
"""任务分解
|
||||
"""任务分解(支持分解到天或仅仅到工段)
|
||||
|
||||
任务分解
|
||||
"""
|
||||
|
@ -82,7 +91,7 @@ class UtaskViewSet(CustomModelViewSet):
|
|||
utasks = Utask.objects.filter(
|
||||
id__in=vdata['ids'], state=Utask.UTASK_CREATED)
|
||||
for i in utasks:
|
||||
PmService.schedue_mtasks(request.user, i)
|
||||
PmService.schedue_mtasks(request.user, i, vdata["schedule_type"])
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=False, perms_map={'post': 'utask.assgin'}, serializer_class=PkSerializer)
|
||||
|
|
Loading…
Reference in New Issue