#define STACKABLE_ARTICLES
#define USE_TEMP_OND_TABLE
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
private const string sqlSelectOrderNeedsDestination =
"select ond.ArticleID,ond.Size1,ond.Size2,ond.Size3,ond.MeasuredArticleQuantity,ond.PlannedQuantity" +
",(a.AllowXYRotation & isnull(cs.AllowXYRotation,1)) as AllowXYRotation" +
",(a.AllowZRotation & isnull(cs.AllowZRotation,1)) as AllowZRotation" +
",a.AllowXYRotation,a.AllowZRotation" +
",ond.OrderID,ond.PutID" +
",a.MaxStack,a.StackDeltaX,a.StackDeltaY,a.StackDeltaZ" +
@",ArticlePriority,AssignmentVolume
from " + vw_OrderNeedsDestination + @" ond
join core.Article a on a.ArticleID = ond.MeasuredArticleID"
left join core.Assignment o on o.AssignmentID = ond.PutID
left join core.CubingStrategy cs on cs.CubingStrategyID = o.CubingStrategyID"
private const string sqlContainerTypeAndAreaGroupID =
"(@pContainerType is null or ond.ContainerType = @pContainerType)"
and (ond.Area = @pArea or @pArea is null)";
and (@pAreaGroupID is null
from core.AreaAreaGroup aag
on aag.Area = ar.ParentArea
where aag.AreaGroupID = @pAreaGroupID
private const string sqlWhereOrder = @"
where OrderID = @pStartOrderID
and " + sqlContainerTypeAndAreaGroupID;
private const string sqlDestinationRouteStopID = "RouteID";
private const string sqlDestinationRouteStopID = "DestinationRouteStopID";
private const string sqlWhereRoute = @"
where @pPackByRouteStop = 1
and ond." + sqlDestinationRouteStopID + @" is not null
and OrderID != @pStartOrderID
and ond." + sqlDestinationRouteStopID + @" in (select " + sqlDestinationRouteStopID + @" from core.Assignment where AssignmentID = @pStartOrderID)
and " + sqlContainerTypeAndAreaGroupID;
private const string sqlQueryOrderItems = sqlSelectOrderNeedsDestination + sqlWhereOrder + @"
" + sqlSelectOrderNeedsDestination + sqlWhereRoute + @"
order by ArticlePriority desc, AssignmentVolume desc
private const string sqlQueryOrderItems = sqlSelectOrderNeedsDestination + @"
where " + sqlContainerTypeAndAreaGroupID + @"
order by ArticlePriority desc, AssignmentVolume desc";
private static SqlCommand CreateCommandOrderItems()
var cmd = new SqlCommand(sqlQueryOrderItems);
cmd.Parameters.Add("@pStartOrderID", SqlDbType.Int);
cmd.Parameters.Add("@pPackByRouteStop", SqlDbType.Int);
cmd.Parameters.Add("@pContainerType", SqlDbType.VarChar, 50);
cmd.Parameters.Add("@pArea", SqlDbType.VarChar, 50);
cmd.Parameters.Add("@pAreaGroupID", SqlDbType.Int);
public static void AddOrderItems(SqlConnection connection, IList<Item> items, Container container,
SqlInt32 StartOrderID, SqlInt32 PackByRouteStop, SqlString ContainerType,
string OverrideQuery = null)
SqlCommand OrderItemsCommand = null;
if (!string.IsNullOrEmpty(OverrideQuery))
OrderItemsCommand = new SqlCommand(OverrideQuery, connection);
OrderItemsCommand.Parameters.Add("@pStartOrderID", SqlDbType.Int).SqlValue = StartOrderID;
OrderItemsCommand.Parameters.Add("@pPackByRouteStop", SqlDbType.Int).SqlValue = PackByRouteStop;
OrderItemsCommand.Parameters.Add("@pContainerType", SqlDbType.VarChar, 50).SqlValue = ContainerType;
OrderItemsCommand.Parameters.Add("@pArea", SqlDbType.VarChar, 50).SqlValue = Area;
OrderItemsCommand.Parameters.Add("@pAreaGroupID", SqlDbType.Int).SqlValue = AreaGroupID;
OrderItemsCommand = new SqlCommand(sqlQueryOrderItems, connection);
OrderItemsCommand.Parameters.Add("@pStartOrderID", SqlDbType.Int).SqlValue = StartOrderID;
OrderItemsCommand.Parameters.Add("@pPackByRouteStop", SqlDbType.Int).SqlValue = PackByRouteStop;
OrderItemsCommand.Parameters.Add("@pContainerType", SqlDbType.VarChar, 50).SqlValue = ContainerType;
OrderItemsCommand.Parameters.Add("@pArea", SqlDbType.VarChar, 50).SqlValue = Area;
OrderItemsCommand.Parameters.Add("@pAreaGroupID", SqlDbType.Int).SqlValue = AreaGroupID;
using (OrderItemsCommand)
using (SqlDataReader reader = OrderItemsCommand.ExecuteReader())
var ArticleID = reader.GetSqlInt32(i++);
var SizeX = GetDecimal(reader, ref i, 0);
var SizeY = GetDecimal(reader, ref i, 0);
var SizeZ = GetDecimal(reader, ref i, 0);
var artquantity = GetDecimal(reader, ref i, 0);
var plannedQuantity = GetDecimal(reader, ref i, 0);
var allowXYRotation = GetBoolean(reader, ref i, true);
var allowZRotation = GetBoolean(reader, ref i, true);
var orderID = GetInt32(reader, ref i, 0);
var putID = GetInt32(reader, ref i, 0);
var weight = GetDecimal(reader, ref i, 0);
var maxStack = GetInt32(reader, ref i, 1);
stackDeltaX = GetDecimal(reader, ref i, 0);
stackDeltaY = GetDecimal(reader, ref i, 0);
stackDeltaZ = GetDecimal(reader, ref i, 0);
var quantity = (int)(artquantity > 0 ? System.Math.Ceiling(plannedQuantity / artquantity) : plannedQuantity);
if (!ArticleID.IsNull && quantity > 0)
StackItem(new Item(ArticleID.Value, (decimal)SizeX, (decimal)SizeY, (decimal)SizeZ, quantity)
ArticleQuantity = (int)artquantity,
PlannedQuantity = (int)plannedQuantity,
AllowXZRotation = allowXYRotation,
AllowYRotation = allowZRotation
StackDelta1 = stackDeltaX,
StackDelta2 = stackDeltaZ,
StackDelta3 = stackDeltaY
OrderItemsCommand.Connection = null;
private const string sqlQueryItemsFunc = @"IF EXISTS (select null
where object_id = OBJECT_ID(N'[core].[BinpackingContainerItems]')
AND type IN ( N'FN', N'IF', N'TF', N'FS', N'FT' ))
select ArticleID,SizeX,SizeY,SizeZ,Quantity,PlannedQuantity" +
",AllowXYRotation,AllowZRotation" +
",MaxStack,StackDeltaX,StackDeltaY,StackDeltaZ" +
@" from [core].[BinpackingContainerItems] (@pContainerID);
private const string sqlQueryItemsFunc = "";
private const string sqlQueryItems = sqlQueryItemsFunc +
"select asgn.ArticleID,wa.SizeX,wa.SizeY,wa.SizeZ,wa.Quantity,asgn.PlannedQuantity" +
",(wa.AllowXYRotation & isnull(cs.AllowXYRotation,1)) as AllowXYRotation" +
",(wa.AllowZRotation & isnull(cs.AllowZRotation,1)) as AllowZRotation" +
",wa.AllowXYRotation,wa.AllowZRotation" +
",wa.MaxStack,wa.StackDeltaX,wa.StackDeltaY,wa.StackDeltaZ" +
from core.Assignment asgn join core.Article a on a.ArticleID = asgn.ArticleID
select top 1 wa.SizeX,wa.SizeY,wa.SizeZ,wa.Quantity,wa.AllowXYRotation,wa.AllowZRotation" +
",wa.Weight / wa.Quantity as ArticleWeight" +
",wa.MaxStack,wa.StackDeltaX,wa.StackDeltaY,wa.StackDeltaZ" +
where wa.BaseArticleID = a.BaseArticleID
order by abs(wa.Quantity - a.Quantity),
case when wa.ArticleID = a.ArticleID then 0 else 1 end" +
where wa.BaseArticleID = a.BaseArticleID
and wa.Weight is not null
and wa.Volume is not null
and wa.ArticleStatus != 'INACTIVE'
order by abs(wa.Quantity - a.Quantity),
case when wa.ArticleID = a.ArticleID then 0 else 1 end" +
left join core.CubingStrategy cs on cs.CubingStrategyID = asgn.CubingStrategyID" +
where (asgn.DestinationLocationID = @pContainerID)";
private static SqlCommand CreateItemsCommand()
var cmd = new SqlCommand(sqlQueryItems);
cmd.Parameters.Add("@pContainerID", SqlDbType.Int);
public static void AddItems(SqlConnection connection, IList<Item> items, Container container, SqlInt32 ContainerID)
var ItemsCommand = new SqlCommand(sqlQueryItems, connection);
ItemsCommand.Parameters.Add("@pContainerID", SqlDbType.Int).SqlValue = ContainerID;
using (SqlDataReader reader = ItemsCommand.ExecuteReader())
var ArticleID = reader.GetSqlInt32(i++);
var SizeX = GetDecimal(reader, ref i, 0);
var SizeY = GetDecimal(reader, ref i, 0);
var SizeZ = GetDecimal(reader, ref i, 0);
var artquantity = GetDecimal(reader, ref i, 0);
var plannedQuantity = GetDecimal(reader, ref i, 0);
var allowXYRotation = GetBoolean(reader, ref i, true);
var allowZRotation = GetBoolean(reader, ref i, true);
var putID = GetInt32(reader, ref i, -1);
var weight = GetDecimal(reader, ref i, 0);
var maxStack = GetInt32(reader, ref i, 1);
stackDeltaX = GetDecimal(reader, ref i, 0);
stackDeltaY = GetDecimal(reader, ref i, 0);
stackDeltaZ = GetDecimal(reader, ref i, 0);
var quantity = (int)(artquantity > 0 ? System.Math.Ceiling(plannedQuantity / artquantity) : plannedQuantity);
if (!ArticleID.IsNull && quantity > 0)
StackItem(new Item(ArticleID.Value, (decimal)SizeX, (decimal)SizeY, (decimal)SizeZ, quantity)
ArticleQuantity = (int)artquantity,
PlannedQuantity = (int)plannedQuantity,
AllowXZRotation = allowXYRotation,
AllowYRotation = allowZRotation
StackDelta1 = stackDeltaX,
StackDelta2 = stackDeltaZ,
StackDelta3 = stackDeltaY
ItemsCommand.Connection = null;
private static decimal GetDecimal(SqlDataReader reader, ref int i, decimal defaultvalue = 0)
var value = (i >= reader.FieldCount || reader.IsDBNull(i))
: System.Convert.ToDecimal(reader.GetValue(i));
private static int GetInt32(SqlDataReader reader, ref int i, int defaultvalue = 0)
var value = (i >= reader.FieldCount || reader.IsDBNull(i))
: System.Convert.ToInt32(reader.GetValue(i));
private static bool GetBoolean(SqlDataReader reader, ref int i, bool defaultvalue = false)
var value = (i >= reader.FieldCount || reader.IsDBNull(i))
: System.Convert.ToBoolean(reader.GetValue(i));
public static void Main()
Console.WriteLine("declare @pStartOrderID int = null;");
Console.WriteLine("declare @pPackByRouteStop bit = null;");
Console.WriteLine("declare @pContainerType varchar(50) = null;");
Console.WriteLine("declare @pArea varchar(50) = null;");
Console.WriteLine("declare @pAreaGroupID int = null;");
Console.WriteLine("declare @pContainerID int = null;");
Console.WriteLine("-----------------");
Console.WriteLine(sqlQueryOrderItems);
Console.WriteLine("-----------------");
Console.WriteLine(sqlQueryItems);
private const string functionSuffix = "";
private const string vw_OrderNeedsDestination = "outbound.vw_OrderNeedsDestination";
private const string vw_OrderNeedsDestination = "#tempOrderNeedsDestination";
private const SystemDataAccessKind systemDataAccessKind = SystemDataAccessKind.Read;
private const DataAccessKind dataAccessKind = DataAccessKind.Read;
private const decimal maxResizeSidePercentage = 0.5m;
public static List<Item> StackItems(IList<Item> items, Container container)
List<Item> additems = new List<Item>();
foreach (var item in items)
StackItem(item, additems, container);
public static void StackItem(Item item, IList<Item> additems, Container container)
for (i = 1; i < item.MaxStack && i < item.Quantity; i++)
if (ys > container.Height ||
int qtyLeft = item.Quantity - i;
var srcItem = new Item(item);
srcItem.Quantity = qtyLeft;
StackItem(srcItem, additems, container);
public class Container { public decimal Height; public decimal Length; public decimal Width; public decimal MaxWeight;
public Container(int i, decimal x, decimal y ,decimal z) {} }
public int ArticleQuantity;
public int PlannedQuantity;
public bool AllowXZRotation;
public bool AllowYRotation;
public decimal StackDelta1;
public decimal StackDelta2;
public decimal StackDelta3;
public Item(int i, decimal x, decimal y ,decimal z, int q) { }