feat: 依据routepack进行任务派发
This commit is contained in:
parent
14994b424a
commit
436719d9ff
|
@ -207,11 +207,11 @@ class Route(CommonADModel):
|
|||
hour_work = models.FloatField('工时', null=True, blank=True)
|
||||
|
||||
@staticmethod
|
||||
def get_routes(material: Material, autotask: bool = False):
|
||||
def get_routes(material: Material):
|
||||
"""
|
||||
返回工艺路线带车间
|
||||
返回工艺路线带车间(不关联工艺包)
|
||||
"""
|
||||
kwargs = {'material': material}
|
||||
kwargs = {'material': material, 'routepack__isnull': True}
|
||||
# 校验工艺路线是否正常
|
||||
rq = Route.objects.filter(
|
||||
**kwargs).order_by('sort', 'process__sort', 'create_time')
|
||||
|
@ -221,6 +221,4 @@ class Route(CommonADModel):
|
|||
raise ParseError('首步缺少输入/最后一步缺少输出')
|
||||
if not rq.filter(is_count_utask=True).exists():
|
||||
raise ParseError('未指定统计步骤')
|
||||
if autotask:
|
||||
kwargs['is_autotask'] = True
|
||||
return rq
|
||||
|
|
|
@ -207,6 +207,6 @@ class RouteViewSet(CustomModelViewSet):
|
|||
queryset = Route.objects.all()
|
||||
serializer_class = RouteSerializer
|
||||
filterset_class = RouteFilter
|
||||
ordering = ['sort', 'create_time']
|
||||
ordering = ['sort', 'process__sort', 'create_time']
|
||||
select_related_fields = ['material',
|
||||
'process', 'material_in', 'material_out', 'mgroup']
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.12 on 2024-07-03 08:18
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mtm', '0032_auto_20240702_1409'),
|
||||
('pm', '0018_mtask_hour_work'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mtask',
|
||||
name='route',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='mtm.route', verbose_name='关联工艺'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='utask',
|
||||
name='routepack',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='mtm.routepack', verbose_name='关联工艺包'),
|
||||
),
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
from django.db import models
|
||||
from apps.utils.models import CommonADModel, CommonBDModel
|
||||
from apps.mtm.models import Material, Mgroup
|
||||
from apps.mtm.models import Material, Mgroup, RoutePack, Route
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
@ -34,6 +34,7 @@ class Utask(CommonBDModel):
|
|||
)
|
||||
type = models.CharField('任务类型', max_length=10,
|
||||
help_text=str(TASK_TYPE), default='mass')
|
||||
routepack = models.ForeignKey(RoutePack, verbose_name='关联工艺包', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
state = models.PositiveIntegerField(
|
||||
'状态', choices=UTASK_STATES, default=UTASK_CREATED, help_text=str(UTASK_STATES))
|
||||
number = models.CharField('编号', max_length=50, unique=True)
|
||||
|
@ -66,6 +67,7 @@ class Mtask(CommonADModel):
|
|||
(MTASK_STOP, '已停止'),
|
||||
(MTASK_SUBMIT, '已提交')
|
||||
)
|
||||
route = models.ForeignKey(Route, verbose_name='关联工艺', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
type = models.CharField('任务类型', max_length=10,
|
||||
help_text=str(TASK_TYPE), default='mass')
|
||||
state = models.PositiveIntegerField(
|
||||
|
|
|
@ -34,6 +34,8 @@ class UtaskSerializer(CustomModelSerializer):
|
|||
attrs['count_day'] = math.ceil(attrs['count']/rela_days)
|
||||
except Exception:
|
||||
raise ParseError('日均任务数计划失败')
|
||||
if attrs.get('routepack', None):
|
||||
attrs['material'] = attrs['routepack'].material
|
||||
return attrs
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
|
|
|
@ -12,6 +12,24 @@ from typing import List, Union
|
|||
|
||||
class PmService:
|
||||
|
||||
@classmethod
|
||||
def cal_real_task_count(cls, count: int, rate_list):
|
||||
"""
|
||||
计算实际任务数
|
||||
"""
|
||||
r_list = []
|
||||
rate_len = len(rate_list)
|
||||
for ind, val in enumerate(rate_list):
|
||||
indx = ind*1
|
||||
xcount = count*1
|
||||
while indx < rate_len:
|
||||
if indx + 1 == rate_len: # 循环到最后一步
|
||||
break
|
||||
xcount = xcount/(rate_list[indx+1]/100)
|
||||
indx = indx + 1
|
||||
r_list.append(math.ceil(xcount))
|
||||
return r_list
|
||||
|
||||
@classmethod
|
||||
def make_utasks_from_orderitems(cls, user, orderitemIds: List[str], start_date: date, end_date: date, belong_dept: Union[Dept, None]):
|
||||
start_date_str = start_date.strftime('%Y%m%d')
|
||||
|
@ -105,9 +123,15 @@ class PmService:
|
|||
raise ParseError('不支持的排产类型')
|
||||
else:
|
||||
# 获取产品的加工路线
|
||||
rqs = Route.get_routes(product)
|
||||
if utask.routepack: # 指定工艺路线
|
||||
rqs = Route.objects.filter(routepack=utask.routepack).order_by('sort', 'process__sort', 'create_time')
|
||||
else:
|
||||
rqs = Route.get_routes(product)
|
||||
if not rqs.exists():
|
||||
raise ParseError('未配置工艺路线')
|
||||
# 通过出材率校正任务数, out_rate 默认为 100
|
||||
out_rate_list = [rq.out_rate for rq in rqs]
|
||||
count_task_list = cls.cal_real_task_count(count,out_rate_list)
|
||||
# 创建小任务
|
||||
for ind, val in enumerate(rqs):
|
||||
if val.material_out:
|
||||
|
@ -116,7 +140,7 @@ class PmService:
|
|||
raise ParseError(f'第{ind+1}步-无输出物料')
|
||||
if val.material_in:
|
||||
material_in = val.material_in
|
||||
elif ind > 0:
|
||||
elif ind > 0: # 默认是上一步的输出
|
||||
material_in = rqs[ind-1].material_out
|
||||
if val.is_autotask:
|
||||
# 找到工段
|
||||
|
@ -129,18 +153,12 @@ class PmService:
|
|||
else: # 后面可能会指定车间
|
||||
raise ParseError(f'第{ind+1}步-工段存在多个!')
|
||||
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)
|
||||
task_count_day = math.ceil(count_task_list[ind]/rela_days)
|
||||
if rela_days >= 1:
|
||||
for i in range(rela_days):
|
||||
task_date = start_date + timedelta(days=i)
|
||||
Mtask.objects.create(**{
|
||||
'route': val,
|
||||
'number': f'{number}_r{ind+1}_{i+1}',
|
||||
'type': utask.type,
|
||||
'material_out': halfgood,
|
||||
|
@ -156,12 +174,13 @@ class PmService:
|
|||
})
|
||||
elif schedule_type == 'to_mgroup':
|
||||
Mtask.objects.create(**{
|
||||
'route': val,
|
||||
'number': f'{number}_r{ind+1}',
|
||||
'type': utask.type,
|
||||
'material_out': halfgood,
|
||||
'material_in': material_in,
|
||||
'mgroup': mgroup,
|
||||
'count': count,
|
||||
'count': count_task_list[ind],
|
||||
'start_date': start_date,
|
||||
'end_date': end_date,
|
||||
'utask': utask,
|
||||
|
|
Loading…
Reference in New Issue