コード例 #1
0
        public IHttpActionResult GetVirtualTrucks(string query = null)
        {
            try
            {
                List <Location>      Items          = Utilities.GetProductionPlanByCountry(query);
                List <ShipmentGroup> ShipmentGroups = Utilities.GetShipmentGroups();
                List <VirtualTruck>  Trucks         = new List <VirtualTruck>();

                if (Items.Any())
                {
                    ProductMachineEfficiencyKeeper EfficiencyKeeper = new ProductMachineEfficiencyKeeper();
                    EfficiencyKeeper.Items = Utilities.GetProductMachineEfficiencies();

                    //let's create first truck
                    VirtualTruck currTruck = null;
                    int          counter   = 0;

                    foreach (Location currLoc in Items.OrderBy(i => i.TotalPallets))
                    {
                        Logger.Info("Lokacja: {loc}", currLoc.L);
                        //let's plan trucks starting from those locations, that have the fewest pallets

                        if (currTruck != null)
                        {
                            //location has changed. each location to have separate truck for now
                            Logger.Info("Dodaje samochód do lokacji: {L}, palet: {pal}", currTruck.L, currTruck.TotalPallets);
                            currTruck.Compose();
                            Trucks.Add(currTruck);
                            currTruck = null;
                        }
                        foreach (ProductionPlanItem p in currLoc.Parts.OrderBy(p => p.END_DATE))
                        {
                            counter = 0;
                            while (p.PAL > 0.9 && counter < 10)
                            {
                                Logger.Info("Operacja: {op}, przejście: {counter}", p.OPERATION_NR, counter);
                                //while this order hasn't been consumed
                                if (currTruck != null)
                                {
                                    if (currTruck.Pallets2Full == 0)
                                    {
                                        //we can't add any pallet to current truck
                                        Logger.Info("Dodaje samochód do lokacji: {L}, palet: {pal}", currTruck.L, currTruck.TotalPallets);
                                        currTruck.Compose();
                                        Trucks.Add(currTruck);
                                        currTruck = null;
                                    }
                                }

                                if (currTruck == null)
                                {
                                    //we have to create new truck
                                    Logger.Info("Nowe auto do: {L}", p.LOCATION);
                                    currTruck   = new VirtualTruck();
                                    currTruck.L = p.LOCATION;
                                }
                                double palletCount = p.QUANTITY / p.PAL;

                                ProductionPlanItem pi = new ProductionPlanItem();
                                pi = p.CloneJson();

                                Logger.Info("Ilość palet w operacji: {op}, pozostało na aucie: {rem}", p.PAL, currTruck.Pallets2Full);
                                if (p.PAL < currTruck.Pallets2Full)
                                {
                                    currTruck.Parts.Add(pi);
                                    currTruck.TotalPallets += p.PAL;
                                    p.PAL      = 0;
                                    p.QUANTITY = 0;
                                }
                                else
                                {
                                    //part of this operation will go to current truck and part will go to next truck
                                    pi.PAL                  = currTruck.Pallets2Full;
                                    pi.QUANTITY             = Convert.ToInt64(pi.PAL * palletCount);
                                    currTruck.TotalPallets += pi.PAL;
                                    currTruck.Parts.Add(pi);
                                    //as we don't consume the whole operation,
                                    //we must adjust the REMAINING & CONSUMED parts (stop date, quantity, etc)
                                    p.PAL      -= pi.PAL; //subtract pallets you've taken
                                    p.QUANTITY -= pi.QUANTITY;
                                    long?minutesTaken = EfficiencyKeeper.Amount2Minutes(pi.MACHINE_ID, pi.PRODUCT_ID, pi.QUANTITY);
                                    if (minutesTaken != null)
                                    {
                                        //we have the efficiency set in MES
                                        pi.STOP_DATE = pi.START_DATE.AddMinutes((double)minutesTaken);
                                        p.START_DATE = pi.STOP_DATE; //stop date of this part is beginning of next part
                                    }
                                }
                                counter++;
                            }
                        }
                    }

                    return(Ok(Trucks));
                }
                else
                {
                    return(NotFound());
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetProductionPlanByDestinations: Błąd. Szczegóły: {Message}", ex.ToString());
                return(InternalServerError(ex));
            }
        }
コード例 #2
0
ファイル: Utilities.cs プロジェクト: robs23/Local_Api2
        public static List <Location> GetProductionPlanByCountry(string query = null)
        {
            try
            {
                List <Location>           Locations = new List <Location>();
                List <ProductionPlanItem> Items     = GetProductionPlan(query);
                if (Items.Any())
                {
                    List <DividerKeeper> Dividers            = new List <DividerKeeper>();
                    List <DividerItem>   DefaultDestinations = Utilities.GetDefaultDestinations();

                    DateTime start      = Items.Min(i => i.START_DATE);
                    DateTime stop       = Items.Max(i => i.STOP_DATE);
                    TimeSpan span       = stop - start;
                    string   ProductIds = string.Join(",", Items.Select(i => i.PRODUCT_ID).ToList().Distinct());
                    ProductMachineEfficiencyKeeper EfficiencyKeeper = new ProductMachineEfficiencyKeeper();
                    EfficiencyKeeper.Items = Utilities.GetProductMachineEfficiencies(ProductIds);
                    List <Session>       Sessions       = new List <Session>();
                    List <ShipmentGroup> shipmentGroups = Utilities.GetShipmentGroups();

                    foreach (ProductionPlanItem i in Items)
                    {
                        //for each operation
                        //get how to allocate it
                        //What week is this?
                        //info from session dates rather than from operation dates
                        if (!Sessions.Any(s => s.SCHEDULING_ID == i.SCHEDULING_ID))
                        {
                            //we need to create the session and calculate its week/year
                            Session s = new Session();
                            s.SCHEDULING_ID = i.SCHEDULING_ID;
                            s.BEGIN_DATE    = i.BEGIN_DATE;
                            s.END_DATE      = i.END_DATE;
                            s.CalcualatePeriod();
                            Sessions.Add(s);
                        }
                        i.WEEK = Sessions.FirstOrDefault(s => s.SCHEDULING_ID == i.SCHEDULING_ID).Week;
                        i.YEAR = Sessions.FirstOrDefault(s => s.SCHEDULING_ID == i.SCHEDULING_ID).Year;
                        if (!Dividers.Any(d => d.Week == i.WEEK && d.Year == i.YEAR))
                        {
                            //create it
                            DividerKeeper div = new DividerKeeper();
                            div.Week  = i.WEEK;
                            div.Year  = i.YEAR;
                            div.Items = Utilities.GetDivider(i.WEEK, i.YEAR);
                            Dividers.Add(div);
                        }
                        DividerKeeper currDiv     = Dividers.FirstOrDefault(d => d.Week == i.WEEK && d.Year == i.YEAR);
                        double        palletCount = i.QUANTITY / i.PAL; //number of pieces on pallet

                        if (currDiv.Items.Any(x => x.ZfinIndex == i.PRODUCT_NR))
                        {
                        }
                        else
                        {
                            //this product hasn't been found in divider for week X
                            //check futher weeks, maybe it's in week X+1
                            currDiv = null;
                            foreach (DividerKeeper dk in Dividers.Where(d => (d.Week > i.WEEK && d.Year == i.YEAR) || (d.Week <i.WEEK && d.Year> i.YEAR)))
                            {
                                if (dk.Items.Any(y => y.ZfinIndex == i.PRODUCT_NR))
                                {
                                    //it's in divider for next week
                                    currDiv = dk;
                                }
                            }
                        }
                        if (currDiv != null)
                        {
                            foreach (LocationAmount la in currDiv.Items.FirstOrDefault(x => x.ZfinIndex == i.PRODUCT_NR).Locations)
                            {
                                if (i.QUANTITY > 0)
                                {
                                    //if there's nothing left to allocate in this operation, go to next operation
                                    if (la.Amount > 0)
                                    {
                                        //there's still quantity to allocate
                                        if (!Locations.Any(l => l.L.Trim() == la.L.Trim()))
                                        {
                                            //we don't have this location started yet
                                            Location loc = new Location();
                                            loc.L = la.L.Trim();
                                            if (shipmentGroups.Any(s => s.Members.Any(m => m.L.Trim() == loc.L)))
                                            {
                                                loc.ShipmentGroupName = shipmentGroups.FirstOrDefault(s => s.Members.Any(m => m.L.Trim() == loc.L)).Name;
                                            }
                                            Locations.Add(loc);
                                        }
                                        Location           currLoc = Locations.FirstOrDefault(l => l.L.Trim() == la.L.Trim());
                                        ProductionPlanItem p       = new ProductionPlanItem();
                                        p = i.CloneJson();
                                        if (la.Amount >= i.QUANTITY)
                                        {
                                            //this L needs more than operation quantity or all of it
                                            //take only operation quantity then
                                            la.Amount -= i.QUANTITY; //decrease the amount of allocation that remains to this L
                                            i.QUANTITY = 0;
                                            i.PAL      = 0;
                                        }
                                        else
                                        {
                                            //there will remain some quantity for other L
                                            p.QUANTITY -= la.Amount;
                                            p.PAL       = la.Amount / palletCount;
                                            la.Amount   = 0;
                                            i.QUANTITY -= p.QUANTITY;
                                            i.PAL      -= p.QUANTITY / palletCount;
                                            //as we don't consume the whole operation,
                                            //we must adjust the REMAINING & CONSUMED parts (stop date, quantity, etc)
                                            long?minutesTaken = EfficiencyKeeper.Amount2Minutes(i.MACHINE_ID, i.PRODUCT_ID, p.QUANTITY);
                                            if (minutesTaken != null)
                                            {
                                                //we have the efficiency set in MES
                                                p.STOP_DATE  = p.START_DATE.AddMinutes((double)minutesTaken);
                                                i.START_DATE = p.STOP_DATE; //stop date of this part is beginning of next part
                                            }
                                        }
                                        p.LOCATION     = la.L;
                                        p.DIVIDER_WEEK = currDiv.Week;
                                        p.DIVIDER_YEAR = currDiv.Year;
                                        currLoc.Parts.Add(p); // add this part to operations for this location
                                    }
                                }
                            }
                        }
                        else
                        {
                            //It's not divider-based product
                            //take default allocation
                            Location currLoc;

                            if (DefaultDestinations.Any(d => d.ZfinIndex == i.PRODUCT_NR))
                            {
                                LocationAmount la = DefaultDestinations.Where(d => d.ZfinIndex == i.PRODUCT_NR).FirstOrDefault().Locations.FirstOrDefault();
                                //default destination found
                                if (!Locations.Any(l => l.L.Trim() == la.L.Trim()))
                                {
                                    //we don't have this location started yet
                                    Location loc = new Location();
                                    loc.L = la.L.Trim();
                                    if (shipmentGroups.Any(s => s.Members.Any(m => m.L.Trim() == loc.L)))
                                    {
                                        loc.ShipmentGroupName = shipmentGroups.FirstOrDefault(s => s.Members.Any(m => m.L.Trim() == loc.L)).Name;
                                    }
                                    Locations.Add(loc);
                                }
                                currLoc = Locations.FirstOrDefault(l => l.L.Trim() == la.L.Trim());
                            }
                            else
                            {
                                //default destination doesn't exist
                                //add it to unknow collection
                                if (!Locations.Any(l => l.L.Trim() == "LXXX"))
                                {
                                    //we don't have this location started yet
                                    Location loc = new Location();
                                    loc.L = "LXXX";
                                    Locations.Add(loc);
                                }
                                currLoc = Locations.FirstOrDefault(l => l.L.Trim() == "LXXX");
                            }

                            ProductionPlanItem p = new ProductionPlanItem();
                            p              = i.CloneJson();
                            i.QUANTITY     = 0;
                            i.PAL          = 0;
                            p.LOCATION     = currLoc.L;
                            p.DIVIDER_WEEK = 0;   // not divider-based
                            p.DIVIDER_YEAR = 0;   // not divider-based
                            currLoc.Parts.Add(p); // add this part to operations for this location
                        }
                    }
                }
                foreach (Location l in Locations)
                {
                    l.Compose();
                }
                return(Locations);
            }
            catch (Exception ex)
            {
                Logger.Error("GetProductionPlanByDestinations: Błąd. Szczegóły: {Message}", ex.ToString());
                return(null);
            }
        }