feat: 依据routepack进行任务派发

This commit is contained in:
caoqianming 2024-07-03 16:46:01 +08:00
parent 14994b424a
commit 436719d9ff
6 changed files with 64 additions and 18 deletions

View File

@ -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

View File

@ -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']

View File

@ -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='关联工艺包'),
),
]

View File

@ -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(

View File

@ -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):

View File

@ -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,