diff --git a/apps/pm/services.py b/apps/pm/services.py index be120c0e..0e5dc3de 100644 --- a/apps/pm/services.py +++ b/apps/pm/services.py @@ -15,35 +15,51 @@ class PmService: @classmethod def cal_x_task_count(cls, target_materialId:str, target_quantity, route_qs): - # 构建逆向依赖图 {输出物料: [所有能生产它的工序]} + # 构建逆向依赖图 {输出物料ID: [Route]} graph = defaultdict(list) for route in route_qs: - graph[route.material_out.id].append(route) + if route.material_out: # 确保输出物料存在 + graph[route.material_out.id].append(route) - # 存储每个Route记录的生产数量 {route_id: 需生产数量} + # 存储每个物料的需求量 + demands = defaultdict(float) + demands[target_materialId] = target_quantity step_production = defaultdict(int) - # 广度优先逆向遍历(BFS) - queue = deque([(target_materialId, target_quantity)]) + # 逆向遍历,从目标物料开始 + queue = deque([target_materialId]) while queue: - current_material, current_demand = queue.popleft() - for route in graph.get(current_material, []): - # 根据工序类型计算当前工序的生产量 - if route.process.mtype == 20: # 拆分 - production = current_demand * route.div_number / (route.out_rate / 100) - elif route.process.mtype == 30: # 合并 - production = current_demand / route.div_number / (route.out_rate / 100) - else: # 正常 - production = current_demand / (route.out_rate / 100) + current_out_id = queue.popleft() + current_demand = demands.get(current_out_id, 0) + if current_demand <= 0: + continue - # 记录当前工序的生产量(向上取整) - step_production[route.id] = math.ceil(production) + # 处理所有能生产该物料的Route(多路径时需求均分) + routes = graph.get(current_out_id, []) + if not routes: + continue - # 将输入物料需求加入队列 + # 均分需求到所有Route(示例按均分逻辑,可根据业务调整) + demand_per_route = math.ceil(current_demand / len(routes)) if len(routes) > 1 else current_demand + + for route in routes: + # 记录该Route的产出量(向上取整) + step_production[route.id] = math.ceil(demand_per_route) + + # 根据工序类型计算输入需求 + 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.material_in: - queue.append((route.material_in.id, production)) + demands[route.material_in.id] += input_needed + queue.append(route.material_in.id) - return dict(step_production) + return dict(reversed(step_production.items())) @classmethod