fix: cal_x_task_count分配任务数的bug

This commit is contained in:
caoqianming 2025-04-09 13:18:00 +08:00
parent 15ccfbe6f9
commit 8068cb1ca3
1 changed files with 48 additions and 23 deletions

View File

@ -14,54 +14,77 @@ from collections import defaultdict, deque
class PmService:
@classmethod
def cal_x_task_count(cls, target_materialId:str, target_quantity, route_qs):
# 构建逆向依赖图 {输出物料ID: [Route]}
def cal_x_task_count(cls, target_materialId: str, target_quantity, route_qs):
# 构建逆向依赖图 {输出物料ID: [生产该物料的Route]}
graph = defaultdict(list)
graphin = defaultdict(list)
for route in route_qs:
if route.material_out: # 确保输出物料存在
graph[route.material_out.id].append(route)
if route.material_in: # 确保输入物料存在
graphin[route.material_in.id].append((route, False))
# 存储每个物料的需求量
demands = defaultdict(float)
demands[target_materialId] = target_quantity
step_production = defaultdict(int)
# 逆向遍历,从目标物料开始
# 逆向遍历队列,从目标物料开始
queue = deque([target_materialId])
visited = set() # 防止重复处理
while queue:
current_out_id = queue.popleft()
if current_out_id in visited:
continue
visited.add(current_out_id)
current_demand = demands.get(current_out_id, 0)
if current_demand <= 0:
continue
# 处理所有能生产该物料的Route多路径时需求均分
# 获取生产该物料的所有Route
routes = graph.get(current_out_id, [])
if not routes:
continue
continue # 无生产路线,无法继续逆向
# 均分需求到所有Route示例按均分逻辑可根据业务调整
demand_per_route = math.ceil(current_demand / len(routes)) if len(routes) > 1 else current_demand
# 平均分配需求到各Route根据业务需求可能需要调整分配策略
routes_count = len(routes)
base_demand = current_demand // routes_count
remainder = current_demand % routes_count
for route in routes:
# 记录该Route的产出量向上取整
step_production[route.id] = math.ceil(demand_per_route)
for i, route in enumerate(routes):
# 分配任务数
task_count = base_demand + 1 if i < remainder else base_demand
step_production[route.id] = task_count # 累加任务数
# 根据工序类型计算输入需求
if route.process.mtype == 20: # 拆分工序1个输入拆成多个输出
input_needed = demand_per_route / route.div_number / (route.out_rate / 100)
elif route.process.mtype == 30: # 合并工序多个输入合并为1个输出
input_needed = demand_per_route * route.div_number / (route.out_rate / 100)
else: # 正常工序
input_needed = demand_per_route / (route.out_rate / 100)
# 根据工序类型计算所需输入物料
if route.process.mtype == 20: # 拆分工序
input_needed = math.ceil(task_count / route.div_number / (route.out_rate / 100))
elif route.process.mtype == 30: # 合并工序
input_needed = math.ceil(task_count * route.div_number / (route.out_rate / 100))
else: # 普通工序
input_needed = math.ceil(task_count / (route.out_rate / 100))
# 更新上游物料需求
# 更新输入物料需求并加入队列
if route.material_in:
demands[route.material_in.id] += input_needed
queue.append(route.material_in.id)
return dict(reversed(step_production.items()))
input_material_id = route.material_in.id
demands[input_material_id] += input_needed
for index, (route_in, _) in enumerate(graphin[input_material_id]):
if route_in == route:
graphin[input_material_id][index] = (route_in, True)
can_append = True
for route_in, caled in graphin[input_material_id]:
if caled is False:
can_append = False
break
if can_append:
queue.append(input_material_id)
# 返回各Route的任务数量
return {route.id: step_production.get(route.id, 0) for route in route_qs}
@classmethod
def cal_real_task_count(cls, count: int, rate_list):
"""
@ -236,6 +259,8 @@ class PmService:
'is_count_utask': route.is_count_utask
})
elif schedule_type == 'to_mgroup':
base_demand = count // mgroups_count
remainder = count % mgroups_count
for indx, mgroup in enumerate(mgroups):
Mtask.objects.create(**{
'route': route,
@ -244,7 +269,7 @@ class PmService:
'material_out': material_out,
'material_in': material_in,
'mgroup': mgroup,
'count': math.ceil(count/mgroups_count),
'count': base_demand + 1 if indx < remainder else base_demand,
'start_date': start_date,
'end_date': end_date,
'utask': utask,