物料List分配给订单List

using System;
using System.Collections.Generic;
using System.Linq;


namespace MaterialAllocationSimulator
{
    // 物料类
    public class Material
    {
        public string Id { get; set; }        // 物料ID
        public string Name { get; set; }      // 物料名称
        public int Quantity { get; set; }     // 可用数量
        public int InitialQuantity { get; set; } // 初始数量(用于展示)


        public Material(string id, string name, int quantity)
        {
            Id = id;
            Name = name;
            Quantity = quantity;
            InitialQuantity = quantity;
        }
    }


    // 订单类(每个订单只包含一种物料)
    public class Order
    {
        public string Id { get; set; }              // 订单ID
      //  public string CustomerName { get; set; }    // 客户名称
        public DateTime DeliveryDate { get; set; }  // 交货日期
     //   public bool IsPriorityCustomer { get; set; } // 是否为优先客户
        public string MaterialId { get; set; }      // 所需物料ID(单一物料)
        public int RequiredQuantity { get; set; }   // 需求数量
        public int AllocatedQuantity { get; set; }  // 已分配数量
        public int FinalRemainingAllocation { get; set; } // 从剩余物料中分配的数量


        //public Order(string id, string customerName, DateTime deliveryDate,
        //           bool isPriorityCustomer, string materialId, int requiredQuantity)
        public Order(string id, DateTime deliveryDate,string materialId, int requiredQuantity)
        {
            Id = id;
        //    CustomerName = customerName;
            DeliveryDate = deliveryDate;
          //  IsPriorityCustomer = isPriorityCustomer;
            MaterialId = materialId;
            RequiredQuantity = requiredQuantity;
            AllocatedQuantity = 0;
            FinalRemainingAllocation = 0;
        }


        // 剩余需求量(初始分配后)
        public int RemainingQuantity => RequiredQuantity - AllocatedQuantity;


        // 最终获得的总数量
        public int TotalReceived => AllocatedQuantity + FinalRemainingAllocation;


        // 最终获得量超过需求量的部分(如果有)
        public int OverAllocation => TotalReceived > RequiredQuantity ? TotalReceived - RequiredQuantity : 0;
    }


    // 分配结果类
    public class AllocationResult
    {
        public Order Order { get; set; }
        public int AllocatedQuantity { get; set; }  // 已分配数量
        public int ShortageQuantity { get; set; }   // 短缺数量


        public AllocationResult(Order order)
        {
            Order = order;
            AllocatedQuantity = 0;
            ShortageQuantity = 0;
        }
    }


    // 物料分配详情类(用于按物料展示分配情况)
    public class MaterialAllocationDetail
    {
        public Material Material { get; set; }
        public List<Tuple<Order, int>> Allocations { get; set; } // 分配给各订单的数量
        public int TotalAllocated { get; set; } // 总分配量
        public int RemainingQuantity { get; set; } // 剩余量
        public Order FinalRemainingOrder { get; set; } // 获得剩余物料的最后一个订单
        public int FinalRemainingAllocated { get; set; } // 分配的剩余物料数量


        public MaterialAllocationDetail(Material material)
        {
            Material = material;
            Allocations = new List<Tuple<Order, int>>();
            TotalAllocated = 0;
            RemainingQuantity = material.Quantity;
            FinalRemainingOrder = null;
            FinalRemainingAllocated = 0;
        }
    }


    // 物料分配管理器
    public class AllocationManager
    {
        private List<Material> _availableMaterials;
        private List<Order> _pendingOrders;
        private List<Order> _sortedOrders;


        public AllocationManager(List<Material> materials, List<Order> orders)
        {
            _availableMaterials = materials;
            _pendingOrders = orders;
            _sortedOrders = new List<Order>();
        }


        // 按优先级排序订单
        public List<Order> SortOrdersByPriority()
        {
            // 排序规则:
            // 1. 交货日期早的优先
            // 2. 同一交货日期,订单ID小的优先
            _sortedOrders = _pendingOrders
                .OrderBy(o => o.DeliveryDate)
               // .ThenByDescending(o => o.IsPriorityCustomer)
                .ThenBy(o => o.Id)
                .ToList();
            return _sortedOrders;
        }


        // 执行物料分配
        public List<AllocationResult> AllocateMaterials()
        {
            var sortedOrders = SortOrdersByPriority();
            var results = new List<AllocationResult>();


            // 第一次分配:按优先级正常分配
            foreach (var order in sortedOrders)
            {
                var result = new AllocationResult(order);
                // 查找可用物料
                var material = _availableMaterials.FirstOrDefault(m => m.Id == order.MaterialId);
                if (material == null)
                {
                    // 物料不存在,全部短缺
                    result.ShortageQuantity = order.RemainingQuantity;
                    results.Add(result);
                    continue;
                }
                // 计算可分配数量(不超过需求)
                int allocatableQuantity = Math.Min(order.RemainingQuantity, material.Quantity);


                if (allocatableQuantity > 0)
                {
                    // 分配物料
                    order.AllocatedQuantity += allocatableQuantity;
                    material.Quantity -= allocatableQuantity;
                    result.AllocatedQuantity = allocatableQuantity;
                }
                // 检查是否仍有短缺
                result.ShortageQuantity = order.RemainingQuantity;
                results.Add(result);
            }
            // 第二次分配:将剩余物料全部分配给最后一个订单(不受需求量限制)
            AllocateRemainingMaterialsToLastOrder();
            return results;
        }


        // 将剩余物料全部分配给最后一个订单(允许超过其需求量)
        private void AllocateRemainingMaterialsToLastOrder()
        {
            // 遍历每种物料
            foreach (var material in _availableMaterials)
            {
                // 如果有剩余物料
                if (material.Quantity > 0)
                {
                    // 找到使用该物料且排序在最后的订单
                    var lastOrderForMaterial = _sortedOrders
                        .Where(o => o.MaterialId == material.Id)
                        .LastOrDefault();


                    // 如果存在这样的订单
                    if (lastOrderForMaterial != null)
                    {
                        // 关键修改:将所有剩余物料分配给最后一个订单,不考虑其原始需求量
                        int canAllocate = material.Quantity;


                        if (canAllocate > 0)
                        {
                            // 分配所有剩余物料
                            lastOrderForMaterial.FinalRemainingAllocation = canAllocate;
                            material.Quantity -= canAllocate;
                        }
                    }
                }
            }
        }


        // 按物料整理分配详情
        public List<MaterialAllocationDetail> GetMaterialAllocationDetails()
        {
            var details = new List<MaterialAllocationDetail>();


            foreach (var material in _availableMaterials)
            {
                var detail = new MaterialAllocationDetail(material);


                // 找到所有使用该物料的订单
                var relatedOrders = _sortedOrders.Where(o => o.MaterialId == material.Id).ToList();


                foreach (var order in relatedOrders)
                {
                    int totalGiven = order.AllocatedQuantity + order.FinalRemainingAllocation;
                    if (totalGiven > 0)
                    {
                        detail.Allocations.Add(Tuple.Create(order, totalGiven));
                        detail.TotalAllocated += totalGiven;
                    }
                }


                // 记录获得剩余物料的订单
                detail.FinalRemainingOrder = relatedOrders.LastOrDefault();
                if (detail.FinalRemainingOrder != null)
                {
                    detail.FinalRemainingAllocated = detail.FinalRemainingOrder.FinalRemainingAllocation;
                }


                // 剩余数量
                detail.RemainingQuantity = material.Quantity;


                details.Add(detail);
            }
            return details;
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("===== 模具生产物料分配模拟系统 =====");
            Console.WriteLine("(最后一个订单获取全部剩余物料,不受需求量限制)");
            Console.WriteLine();


            // 创建模拟物料(模具生产的零件)
            var materials = new List<Material>
            {
                new Material("M001", "模具A生产的零件", 1000),
                new Material("M002", "模具B生产的零件", 300),
                new Material("M003", "模具C生产的零件", 200)
            };


            // 创建模拟订单(每个订单只包含一种物料)
            var orders = new List<Order>
            {
                new Order("O001"new DateTime(2025, 8, 10),  "M001", 350),
                new Order("O002",new DateTime(2025, 8, 5),  "M001", 150),
                new Order("O003",new DateTime(2025, 8, 5), "M002", 200),
                new Order("O004"new DateTime(2025, 8, 3), "M001", 300),
                new Order("O005", new DateTime(2025, 8, 8),  "M002", 100),
                new Order("O006", new DateTime(2025, 8, 6),"M003", 180),
                new Order("O007",new DateTime(2025, 8, 12), "M001", 100),
                new Order("O008",new DateTime(2025, 8, 11), "M001", 100),
                new Order("O009",new DateTime(2025, 8, 15), "M001", 100)
                /*new Order("O001", "常规客户A", new DateTime(2025, 8, 10), false, "M001", 350),
                new Order("O002", "优先客户B", new DateTime(2025, 8, 5), true, "M001", 150),
                new Order("O003", "常规客户C", new DateTime(2025, 8, 5), false, "M002", 200),
                new Order("O004", "优先客户D", new DateTime(2025, 8, 3), true, "M001", 300),
                new Order("O005", "常规客户E", new DateTime(2025, 8, 8), false, "M002", 100),
                new Order("O006", "优先客户F", new DateTime(2025, 8, 6), true, "M003", 180),
                new Order("O007", "常规客户G", new DateTime(2025, 8, 12), false, "M001", 100)*/
            };


            // 创建分配管理器并执行分配
            var manager = new AllocationManager(materials, orders);
            var results = manager.AllocateMaterials();


            // 获取按物料视角的分配详情
            var materialDetails = manager.GetMaterialAllocationDetails();


            // 显示订单优先级排序(供参考)
            Console.WriteLine("===== 订单优先级排序(供参考) =====");
            var sortedOrders = manager.SortOrdersByPriority();
            foreach (var order in sortedOrders)
            {
                //Console.WriteLine($"订单 {order.Id} - 客户: {order.CustomerName} " +
                //              $"- 交货日期: {order.DeliveryDate:yyyy-MM-dd} " +
                //              $"- {(order.IsPriorityCustomer ? "优先客户" : "常规客户")} " +
                //              $"- 物料: {order.MaterialId}");
                Console.WriteLine($"订单 {order.Id}  " +
                              $"- 交货日期: {order.DeliveryDate:yyyy-MM-dd} " +
                                                           $"- 物料: {order.MaterialId}");
            }


            Console.WriteLine();
            Console.WriteLine("===== 物料分配详情(按物料视角) =====");
            foreach (var detail in materialDetails)
            {
                Console.WriteLine($"物料: {detail.Material.Name} ({detail.Material.Id})");
                Console.WriteLine($"  初始总量: {detail.Material.InitialQuantity}个");
                Console.WriteLine($"  正常分配量: {detail.TotalAllocated - detail.FinalRemainingAllocated}个");


                if (detail.FinalRemainingAllocated > 0)
                {
                    Console.WriteLine($"  剩余物料分配: {detail.FinalRemainingAllocated}个 " +
                                  $"(分配给最后一个订单 {detail.FinalRemainingOrder?.Id})");
                }


                Console.WriteLine($"  总分配量: {detail.TotalAllocated}个");
                Console.WriteLine($"  最终剩余: {detail.RemainingQuantity}个");


                if (detail.Allocations.Count > 0)
                {
                    Console.WriteLine("  分配明细:");
                    foreach (var allocation in detail.Allocations)
                    {
                        var order = allocation.Item1;
                        var quantity = allocation.Item2;
                        string extraInfo = order.FinalRemainingAllocation > 0
                            ? $" (含剩余分配 {order.FinalRemainingAllocation}个)"
                            : "";


                        // 显示超额分配信息(如果有)
                        string overAllocationInfo = order.OverAllocation > 0
                            ? $" (超额分配: {order.OverAllocation}个)"
                            : "";


                        Console.WriteLine($"    订单 {order.Id}: {quantity}个 " +
                                      $"(需求: {order.RequiredQuantity}个){extraInfo}{overAllocationInfo}");
                    }
                }
                else
                {
                    Console.WriteLine("  未分配给任何订单");
                }
                Console.WriteLine();
            }


            // 显示各订单的最终分配情况
            Console.WriteLine("===== 各订单最终分配情况 =====");
            foreach (var order in orders.OrderBy(o => o.Id))
            {
                var material = materials.FirstOrDefault(m => m.Id == order.MaterialId);
                string materialName = material != null ? material.Name : "未知物料";


                Console.WriteLine($"订单 {order.Id} :");
                //  Console.WriteLine($"订单 {order.Id} ({order.CustomerName}):");
                Console.WriteLine($"  物料: {materialName} ({order.MaterialId})");
                Console.WriteLine($"  需求数量: {order.RequiredQuantity}个");
                Console.WriteLine($"  正常分配: {order.AllocatedQuantity}个");


                if (order.FinalRemainingAllocation > 0)
                {
                    Console.WriteLine($"  从剩余物料中分配: {order.FinalRemainingAllocation}个");
                }


                Console.WriteLine($"  总共获得: {order.TotalReceived}个");


                // 显示超额分配信息(如果有)
                if (order.OverAllocation > 0)
                {
                    Console.WriteLine($"  超额分配: {order.OverAllocation}个");
                }


                Console.WriteLine();
            }


            Console.WriteLine("模拟完成,按任意键退出...");
            Console.ReadLine();
        }
    }
}

 

posted @ 2025-07-26 14:05  知行一体2  阅读(5)  评论(0)    收藏  举报