On-Demand Cartonization
16 min
intro to box type generators the modern distribution center often contains machines that can build custom boxes in real time based on a customer's specific order these machines help reduce waste and product damage, as well as reduce the chance of incurring dimensional weight fees the paccurate api is able to not only replicate this on demand logic, but greatly improve upon it by integrating cost awareness paccurate's optimized boxes can then be used to inform the box on demand machine what size carton to build for the order read more about how paccurate helps hunter douglas control their box cutting machines in this case study https //paccurate io/case studies/hunter douglas from best guess to dynamic optimized shipping using paccurate with box on demand machines requires the use of boxtypegenerators in the api box type generators incorporate many inputs, all of which we will explore here initializing the box type generator list at its core, boxtypegenerators is an array of boxtypegenerator objects that include the same attributes as any provided boxtype , along with the configuration options for the dynamic box creation each box type generator (btg) supports 3 top level inputs boxtypedefaults a box object that contains the default properties of the generated box here you would define a name, refid, maxweight or any additional box property https //paccurate readme io/docs/item and box limits that the generated box should inherit operation a string, either "cartesian" or "pack as is" the "cartesian" option leverages all of the inputs provided in the options object, while pack as is is used to generate a box with the exact dimensions of an item placed inside of it (most often used as an optional sioc carton) options an object that includes several configuration options which will be outlined below this is where limits, ranges, and pricing thresholds are defined here is an example btg list with two different configured boxtypegenerator objects {"boxtypegenerators" \[ { "boxtypedefaults" { "name" "generated 100", "refid" 100, "weighttare" 0, }, "operation" "cartesian", "options" { "yrange" { "min" 3, "max" 8, "derivefromitems" true }, "xlist" \[ 5 5, 6 5 ], "zrange" { "min" 9, "max" 190 } } }, { "boxtypedefaults" { "name" "generated 200", "refid" 200, "weightmax" 100, "weighttare" 0, "itemsperboxmax" 3, "itemsinlinemax" \[ 1, 2, 2 ], "itemsinlineoverhang" { "y" 24 } }, "operation" "cartesian", "options" { "yrange" { "min" 3, "max" 8, "derivefromitems" true }, "xlist" \[ 5 5, 5 63, 7, 6 5 ], "zrange" { "min" 9, "max" 190, "fitforfirstitem" true }, "pricecomponents" \[ { "key" "oversize", "metric" "length plus girth", "limit" 1, "prices" \[ 0, 1, 53710 ], "thresholds" \[ 0, 105, 165 ] }] } }} we'll explore what all of the settings mean in further detail below configuring the box type generator it's easiest to build a box type generator configuration step by step base properties, operation, and custom properties default box properties the boxtypedefaults object contains box properties that each generated box will inherit at minimum, boxtypedefaults must have a refid property the api will reject a request if the defaults are missing the refid it is recommended to also include a name; this will assist in troubleshooting the pack response and help differentiate between different btg configurations below is an example of a typical boxtypedefaults configuration for a boxtypegenerator some common box packing properties that may be relevant for on demand boxes can be found in our guide to item and box limits https //paccurate readme io/docs/item and box limits for more information around what can be added to boxtypedefaults , visit the boxproperties page in our schema https //api paccurate io/docs/#model boxproperties { "boxtypedefaults" { "name" "generated box", "refid" 200, "weightmax" 100, "weighttare" 0 5 } } choosing an operation for on demand cartonization, you will want to use "operation" "cartesian" which leverages all of the inputs and limits for more information on "operation" "pack as is" , please visit our guide on ship in own container generator parameters & thresholds the options for btgs have 9 available attributes, each with their own subset of parameters these attributes can be broken out into 4 categories axis values, metric limits, price thresholds, and trimming at minimum, a btg requires an axis value for each axis \[x, y, z] the limits and thresholds offer fine grain controls to accurately represent things like surcharges and operational constraints the trimming option determines the level of precision when returning a box dimension axis value definitions there are two ways for paccurate to adjust a box dimension in a given axis range and list in sum, these comprise 6 of the available options xrange, xlist, yrange, ylist, zrange, and zlist 🚧 important you cannot use multiple value definitions for the same axis for example, providing both xrange and xlist will ignore the list value and use the range you can use different value definitions for each axis; a range to derive x, a list to derive y and a list to derive z, for example list the syntax for a list is straightforward it is a list of numbers representing available values for the axis for example "xlist" \[2,4,6] tells the generated box it can only have a height of 2, 4, or 6 no other values would be attempted or returned below is an example of how a box making machine with a fixed footprint (12x16) would be represented this way in the api (using lists) { "boxtypegenerators" \[ { "boxtypedefaults" { "name" "variable height machine" "refid" 100 }, "operation" "cartesian", "options" { "xlist" \[6, 8, 10, 12, 14], "ylist" \[12], "zlist" \[16] } } 	] } in the example, there are 5 available heights provided to the list the footprint is fixed, as ylist and zlist values only include one number range the syntax for a range definition is more complex an axis range has 5 configurable attributes min a number that defines the minimum axis length to generate max a number that defines the maximum axis length to generate derivefromitems a boolean value that when set to true intelligently selects the axis' length based upon the placed item's axis dimension increment subdivisions between possible values for example, with a range of 1 10, setting the increment of 5 would generate possible dimensions of 1, 1 5, 2, 2 5 etc fitforfirstitem a boolean value that if true selects the axis length based upon the first item placed in the generated box this overrides step and derivefromitems the config below uses ranges to generate each axis length the height uses min, max and step, while the length and width use derivefromitems { 	"boxtypegenerators" \[ { "boxtypedefaults" { "name" "generated 12 18 24", "refid" 100, "weightmax" 50, "weighttare" 0 }, "operation" "cartesian", "options" { "xrange" { "min" 3, "max" 12, "step" 3 }, "yrange" { "min" 10, "max" 18, "derivefromitems" true }, "zrange" { "min" 16, "max" 24, "derivefromitems" true } } } ] } the generated boxes from the above would have one of 4 different heights, since the generator is incrementing from the min 3 to the max of 12 in units of 3 the length and width values are derived from the items that are added to the box pass in some items to this configuration https //inspector manage paccurate io/config editor?config=n4igrg9ghgkgngbwkyhekdskcccgaxclazxac4btuswrjaesqdmcbxagzxnnhrwfskzeahmm2fegamawgcmajjkaoafiasiadqgstajksysgazhtadyqblyqas8awrxqyavjmhln+zby6yxgc+2hdiuhhweohcamz+eehevjjr2ugqmfhwfdaqtlaaolaj6hhkefgssceievfcofaasimizkb8vtgkamzafm5g8segcc3obdwgnd0m/yokskrakthwag5iagjyehx6cxxcfvujaf7jkx1drgbs8y6k6itrmzt7b0hh5zvigf8axw0vkoagukjwyjqdppde9tabhfgpcj4obkzygstzdbjertecpwqaonuoziam0zziprgxjszvixmj8lcax4gliiaagpyihskaacbwqnbsquwfi8lqggiqnieiqaykyjhkshvigcof0jamnmrynkiprpaa7csceg8dacy82etsgtqysswbxhtrayjoybeiuirrbawerbqbhcb4ajocn+gvyhvyzvinsumcywrazq62euw0ok15rfwm0nqlgynu7sm2sukaugccnu8jjjfravd9xiaeiljdfciwepjbaciepw3secwekntanfvyluowgag5j5fmc3q4xmqeic2ii9ibnbirapo95mseu2a7iqwrr7slf77eysazfzyqjlkhm2cfxiwea3zmhjevfxajvxhkm1bjntnagbqiga , and you get the results below when deciding whether to use lists vs ranges, there are performance impacts to consider lists provide a fixed number of possible values to generate on each axis, while ranges allow the potential values to change with varying degrees of precision providing a step to a range helps to control the amount of possible lengths that can be generated, thus improving processing time it's encouraged to experiment with these settings and mix and match ranges and lists to get performant results when time is critical metric limits in addition to the axis length limits we just covered, btgs support a list of limits for calculated metrics of the generated box size these limits add boundaries for the generated box sizes not to exceed or fall below each limit object has three values metric a string representing the calculated value to apply the limits to available options are volume , surface area , longest dimension , middle dimension , length plus girth , and girth max a number representing the maximum acceptable value for the metric min a number representing the minimum acceptable value for the metric { 	"boxtypegenerators" \[ { "boxtypedefaults" { "name" "generated 12 18 24", "refid" 100, "weightmax" 50, "weighttare" 0 }, "operation" "cartesian", "options" { "xrange" { "min" 3, "max" 12, "step" 3 }, "yrange" { "min" 10, "max" 18, "derivefromitems" true }, "zrange" { "min" 16, "max" 24, "derivefromitems" true }, "limits" \[ { "metric" "length plus girth", "max" 108 }, { "metric" "volume", "max" 900 } ] } } ] } in the configuration above, there is a maximum length plus girth (longest dimension value + 2x shortest dimension + 2x second shortest dimension), and a maximum volume value of 900 cubic inches pricing components one of the most powerful aspects of boxtypegenerators is being able to leverage cost as the dimensions of a generated box change the pricecomponents parameter enables this cost awareness around the calculated box metrics in addition to volume and weight things like additional handling fees and oversize charges can be captured here and used in the final generated box size each pricing component is comprised of 4 values key a string associated with a specific cost for the component's corresponding metric the key does not have to be unique, as it is possible for other metrics to contribute to the same charge metric a string representing the calculated value to monitor for price implications available options are volume , surface area , longest dimension , middle dimension , length plus girth , and girth thresholds a list of number thresholds of corresponding metric above which corresponding prices are triggered prices a list of integer price values to assign when corresponding thresholds are exceeded while the limits option creates box size restrictions on the calculated metrics, pricingcomponents uses the threshold values that, when exceeded, incur the additional fee from the corresponding item in the prices attribute { \[ { "boxtypedefaults" { "name" "generated 12 24 16", "refid" 100, "weightmax" 50, "weighttare" 0 }, "operation" "cartesian", "options" { "xrange" { "min" 3, "max" 12, "derivefromitems" true }, "yrange" { "min" 3, "max" 24, "derivefromitems" true }, "zrange" { "min" 3, "max" 16, "derivefromitems" true }, "limits" \[ { "metric" "longest dimension", "min" 3, "max" 20 } ], "pricecomponents" \[ { "key" "size change", "metric" "length plus girth", "thresholds" \[ 3, 40, 60 ], "prices" \[ 1, 200, 500 ] } ] } } ] } given the configuration above, a box with a length plus girth value of 45 would cost $2 00, while a value of 60 or more would cost $5 00 also included is a limit for longest dimension of 20 below is how paccurate packs the config https //inspector manage dev paccurate io/config editor/?config=n4iglglgpgtgylcbneaua2qatlazgsqbm0bgaghaecbxaqwdsjibpnazgslbinqtad2fnkaaepaawa6aowbwcq1qksugewkqal0nq5axwob3kgadmacwhoalbxq0eaeaakghamzzauaiqaecak+gbtuslrmucguhgiangjyzgdemrqkagxsaicg2hheagounaxmeeqaxdx8gskoyuykthq6qdagicbmvsx2jldoaok8ufhghv4a6gichlz+aek0cfqgsqljqtiebb4ynnlkbqteqbxudiwszsa1vpxcki0g4sqxsjj6bwgahfidmztjzrbcbk5ucaaiimjachj+acyifo8x8abvqa4nia4olklcumwsdi1dzipkqdgzq0ruvbqgajycbipeovjrm2sajq2qg/c48ro9uh9eaosegabk4syuyciswyaa1knngtumw/mpmvi8gbdcgaiweogxzaadte0jhqyvzhjgb0iejao8shinrlbs4akkiryw+jqzzm/wkxeporpervolktkcv76kk0oqob2iqxuj1eifdkebomhsoicnrtkxhpcuwgrpj1ngkcm81wqaayqsakmuggajrzhgaiqeaatjbydew2aldbrvrxrqiekxnbw3ooaarpbheliooswsgkkl7x+mcknrj8mxzk49pnegslmgnputd57pviay2g4najc6arrxpepna8f9oh4bhcraphy1eurpqyki4xgmb1nbeaya/zqsnucywaanygaaxlaexwaaybecasgokaumyfd6dq14mkwy5cpecloci0ikkomi6iypi2ly9jqe4u4enijncimqtkjgaipzqejgk6ejuegndpmqcypgcri2oicdoyedykbk7c5nqcl9gbs0jm7bflsexgdwwua1sueb+c0kaxw8cxupvhddmmezedmcaldhynwjhmwwcwelcxinakg7ejcdxdgbcdtijgc1y12fj01bfmgvvkpym30ia above as you can see, the single item is less expensive at $2 00, while all of the other items exceed the 40 length + girth threshold, and thus cost $5 00 to ship these costs are in addition to any other pricing information provided to a request, such as a base box cost, rate table, or dim weight trimming dimensions by default, when a box size is generated, paccurate will trim down the dimensions to the bounds of the item inside the box for example, if a generated box size was 8 x 10 x 12, but the boundaries of the items inside were at most 6 75 x 9 66 x 11 3, paccurate returns a box size of 6 75 x 9 66 x 11 3 this feature can be turned off in the btg's options by setting notrimtomaxextent to true if you have configured your generator to make boxes with rounded/fixed dimensional increments, you would want to set "notrimtomaxextent"\ true to make sure the output boxes match the increments you had input this default feature allow paccurate to restrict the number of virtual boxes to choose from while still returning a box that precisely contains the item's inner dimensions, enabling precision without sacrificing processing speed targeting & performance depending on your use case for box type generators, it is often essential to control which items are eligible to be packed using the generator additionally, if you have multiple generators, you may only want specific items to use a specific generator this is where the boxtypedefaults come into play since each btg has a specific refid , it is just a matter of creating the appropriate exclude condition for an item, and using the btg's refid for the targetboxrefids array given the example request used earlier, if we add an exclude rule for the smaller items, they are now packed using a boxtype in the provided array as opposed to in the btg the total cost increases to $20 76 from $17 00 here is the full body of the request, including the exclude rule and boxtypes array { "itemsets" \[ { "refid" 1, "quantity" 3, "dimensions" { "x" 10 75, "y" 11 25, "z" 10 25 }, "weight" 4, "name" "handcrafted soft sausages", "color" "#7a1632" }, { "refid" 2, "quantity" 5, "dimensions" { "x" 3, "y" 4, "z" 4 }, "weight" 2, "name" "generic wooden bacon", "color" "#7c3c74", "sequence" "nobox" }, { "refid" 3, "quantity" 3, "dimensions" { "x" 13, "y" 7 25, "z" 8 5 }, "weight" 3, "name" "awesome metal tuna", "color" "#31724d" }, { "refid" 4, "quantity" 9, "dimensions" { "x" 9 75, "y" 4 5, "z" 3 75 }, "weight" 2, "name" "rustic soft bike", "color" "#382675" } ], "boxtypes" \[ { "refid" 0, "weightmax" 150, "name" "example box 1", "dimensions" { "x" 4, "y" 6, "z" 8 } } ], "rules" \[ { "operation" "exclude", "itemmatch" { "property" "sequence", "expression" "nobox" }, "targetboxrefids" \[ 100 ] } ], "boxtypechoicegoal" "most items", "boxtypegenerators" \[ { "boxtypedefaults" { "name" "generated 12 24 16", "refid" 100, "weightmax" 50, "weighttare" 0 }, "operation" "cartesian", "options" { "xrange" { "min" 3, "max" 12, "derivefromitems" true }, "yrange" { "min" 3, "max" 24, "derivefromitems" true }, "zrange" { "min" 3, "max" 16, "derivefromitems" true }, "limits" \[ { "metric" "longest dimension", "min" 3, "max" 24 } ], "pricecomponents" \[ { "key" "size change", "metric" "length plus girth", "thresholds" \[ 3, 40, 60 ], "prices" \[ 100, 200, 500 ] } ] } } ] } take a look at the guide for constructing rules https //paccurate readme io/docs/building rules#box refids and exclude rules https //paccurate readme io/docs/rule types#exclude for more details on how to create and target items and boxes a final consideration for when implementing box type generators is performance depending on the average quantity of items per order, range of size options, and number of generators in the request, processing times can increase significantly there are a few ways to control this first, ensuring that only items that should use the generator are eligible, using the exclude rules mentioned above second, if using a range axis value definition, you can increase the step value to reduce the number of options available to the range third, and perhaps most straightforward, is a request level option called generatedboxtypesmax this option sets a limit for virtual box types to be generated, which is especially helpful if when using wide ranges that could produce thousands of box size options on each request for example, setting the max box types to 100 https //inspector manage dev paccurate io/config editor/?config=n4iglglgpgtgylcbneaua2qatlazgsqbm0bgaghaecbxaqwdsjibpnazgslbinqtad2fnkaaepaawa6aowbwcq1qksugewkqal0nq5axwob3kgadmacwhoalbxq0eaeaakghamzzauaiqaecak+gbtuslrmucguhgiangjyzgdemrqkagxsaicg2hheagounaxmeeqaxdx8gskoyuykthq6qdagicbmvsx2jldoaok8ufhghv4a6gichlz+aek0cfqgsqljqtiebb4ynnlkbqteqbxudiwszsa1vpxcki0g4sqxsjj6bwgahfidmztjzrbcbk5ucaaiimjachj+acyifo8x8abvqa4nia4olklcumwsdi1dzipkqdgzq0ruvbqgajycbipeovjrm2sajq2qg/c48ro9uh9eaosegabk4syuyciswyaa1knngtumw/mpmvi8gbdcgaiweogxzaadte0jhqyvzhjgb0iejao8shinrlbs4akkiryw+jqzzm/wkxeporpervolktkcv76kk0oqob2iqxuj1eifdkebomhsoicnrtkxhpcuwgrpj1ngkbrejjwh+jzmi3wpc5yte03mq1qadcfgekygwweaocmaesagafpilayiahz3p2nvbaki87vurwarpbheliooswst3cdqcezckntl8npzk49pnegslmgnn3tqfnugaiamvoha0aklobgtpd6mcdxiogfggfxocmfjv5rglbgojjgawhwceqbgidlbke5xjaaa3kaadesarfbobgf4icwagoc6zg8poajxiikjlni95yu4gj6kyli2i4rielafjbnays7je0gk2oizpoymbwpxnboo4rp4m4sbd1uxajg8zxege6iv2jj51gontsi01byx0ztlrssceutirecvdbqdvjqqh4lqogxdwlhw9uyosyy7n4mwiaszdg3czczdalbmtxtkccqcd4kiq8obsj1mgkxz/mpx8ntup8yc9eqfkbfqga=== in the example above returns the 20 items in 5 seconds vs just over 3 seconds https //inspector manage dev paccurate io/config editor/?config=n4iglglgpgtgylcbneaua2qatlazgsqbm0bgaghaecbxaqwdsjibpnazgslbinqtad2fnkaaepaawa6aowbwcq1qksugewkqal0nq5axwob3kgadmacwhoalbxq0eaeaakghamzzauaiqaecak+gbtuslrmucguhgiangjyzgdemrqkagxsaicg2hheagounaxmeeqaxdx8gskoyuykthq6qdagicbmvsx2jldoaok8ufhghv4a6gichlz+aek0cfqgsqljqtiebb4ynnlkbqteqbxudiwszsa1vpxcki0g4sqxsjj6bwgahfidmztjzrbcbk5ucaaiimjachj+acyifo8x8abvqa4nia4olklcumwsdi1dzipkqdgzq0ruvbqgajycbipeovjrm2sajq2qg/c48ro9uh9eaosegabk4syuyciswyaa1knngtumw/mpmvi8gbdcgaiweogxzaadte0jhqyvzhjgb0iejao8shinrlbs4akkiryw+jqzzm/wkxeporpervolktkcv76kk0oqob2iqxuj1eifdkebomhsoicnrtkxhpcuwgrpj1ngkbrejjwh+jzmi3wpc5yte03mq1qadcfgekygwweaocmaesagafpilayiahz3p2nvbaki87vurwarpbheliooswst3cdqcezckntl8npzk49pnegslmgnn3tqfnugaiamvoha0aklobgtpd6mcdxiogfggfxocmfjv5rglbgojjgawhwceqbgidlbke5xjaaa3kaadesarfbobgf4icwagoc6zg8poajxiikjlni95yu4gj6kyli2i4rielafjbnays7je0gk2oizpoymbwpxnboo4rp4m4sbd1uxajg8zxege6iv2jj51gontsi01byx0ztlrssceutirecvdbqdvjqqh4lqogxdwlhw9uyosyy7n4mwiaszdg3czczdalbmtxtkccqcd4kiq8obsj1mgkxz/mpx8ntup8yc9eqfkbfqga===\&embed=true https //inspector manage dev paccurate io/config editor/?config=n4iglglgpgtgylcbneaua2qatlazgsqbm0bgaghaecbxaqwdsjibpnazgslbinqtad2fnkaaepaawa6aowbwcq1qksugewkqal0nq5axwob3kgadmacwhoalbxq0eaeaakghamzzauaiqaecak+gbtuslrmucguhgiangjyzgdemrqkagxsaicg2hheagounaxmeeqaxdx8gskoyuykthq6qdagicbmvsx2jldoaok8ufhghv4a6gichlz+aek0cfqgsqljqtiebb4ynnlkbqteqbxudiwszsa1vpxcki0g4sqxsjj6bwgahfidmztjzrbcbk5ucaaiimjachj+acyifo8x8abvqa4nia4olklcumwsdi1dzipkqdgzq0ruvbqgajycbipeovjrm2sajq2qg/c48ro9uh9eaosegabk4syuyciswyaa1knngtumw/mpmvi8gbdcgaiweogxzaadte0jhqyvzhjgb0iejao8shinrlbs4akkiryw+jqzzm/wkxeporpervolktkcv76kk0oqob2iqxuj1eifdkebomhsoicnrtkxhpcuwgrpj1ngkbrejjwh+jzmi3wpc5yte03mq1qadcfgekygwweaocmaesagafpilayiahz3p2nvbaki87vurwarpbheliooswst3cdqcezckntl8npzk49pnegslmgnn3tqfnugaiamvoha0aklobgtpd6mcdxiogfggfxocmfjv5rglbgojjgawhwceqbgidlbke5xjaaa3kaadesarfbobgf4icwagoc6zg8poajxiikjlni95yu4gj6kyli2i4rielafjbnays7je0gk2oizpoymbwpxnboo4rp4m4sbd1uxajg8zxege6iv2jj51gontsi01byx0ztlrssceutirecvdbqdvjqqh4lqogxdwlhw9uyosyy7n4mwiaszdg3czczdalbmtxtkccqcd4kiq8obsj1mgkxz/mpx8ntup8yc9eqfkbfqga===\&embed=true conclusion box type generators are a very powerful part of the paccurate api they consider and emulate the operational an financial constraints of real box on demand machines, and generate a packing solution optimized for those goals and constraints those packing solutions, available in the api response can then be used to instruct the hardware on what boxes to create to fulfill the order we've learned how to create btgs, set default information, configure range options, incorporate size limits, add pricing components, and even how to optimize performance and create rules to ensure the right items are being sent to the box type generators thank you for reading, and as always, any questions, please reach out at support\@paccurate io mailto\ support\@paccurate io , or visit our forums
