You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
16 KiB
PHP

<?php
/*
* Copyright 2023 Netsyms Technologies
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* - Neither the name of the copyright holder nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Price data from the United States Postal Service as published in Notice 123, effective July 9, 2023.
* Purely factual data, such as the price of a service, is not a creative work.
* It cannot be copyrighted and is therefore in the public domain (Baker v. Selden, 1879).
*/
class RetailPriceChart {
public static function getPrice($weight, $zone, $service = "GroundAdvantage", $dimensions = [4, 6, 1], $rectangular = true) {
rsort($dimensions); // Largest side first
// Calculate and use dimensional weight when required
$cubicinches = round($dimensions[0]) * round($dimensions[1]) * round($dimensions[2]);
if ($rectangular == false) {
// non-rectangular adjustment factor
// https://pe.usps.com/text/dmm300/123.htm section 1.3.2
$cubicinches = $cubicinches * 0.785;
}
if ($cubicinches > 1728) {
$dimweight = ceil($cubicinches / 166) * 16;
if ($dimweight > 70 * 16) {
$dimweight = 70 * 16;
}
$weight = max($weight, $dimweight);
}
if ($service == "GroundAdvantage") {
$sizepenalty = 0;
if ($dimensions[0] > 22 && $dimensions[0] <= 30) {
$sizepenalty += 4;
}
if ($dimensions[0] > 30) {
$sizepenalty += 7;
}
if ($cubicinches > 3456) {
$sizepenalty += 15;
}
if ($dimensions[0] + $dimensions[1] * 2 + $dimensions[2] * 2 > 108) {
// Oversized price
return self::GROUND_ADVANTAGE_LB_PRICES["OVERSIZE"][$zone - 1] + $sizepenalty;
}
if ($weight >= 16) {
$weight = ceil($weight / 16);
return self::GROUND_ADVANTAGE_LB_PRICES[$weight][$zone - 1] + $sizepenalty;
} else {
if ($weight <= 4) {
return self::GROUND_ADVANTAGE_OZ_PRICES[4][$zone - 1] + $sizepenalty;
} else if ($weight <= 8) {
return self::GROUND_ADVANTAGE_OZ_PRICES[8][$zone - 1] + $sizepenalty;
} else if ($weight <= 12) {
return self::GROUND_ADVANTAGE_OZ_PRICES[12][$zone - 1] + $sizepenalty;
} else {
return self::GROUND_ADVANTAGE_OZ_PRICES[15.999][$zone - 1] + $sizepenalty;
}
}
} else if ($service == "Priority") {
$sizepenalty = 0;
if ($dimensions[0] > 22 && $dimensions[0] <= 30) {
$sizepenalty += 4;
}
if ($dimensions[0] > 30) {
$sizepenalty += 15;
}
if ($cubicinches > 3456) {
$sizepenalty += 25;
}
$weight = ceil($weight / 16);
return self::PRIORITY_PRICES[$weight][$zone - 1] + $sizepenalty;
}
}
const GROUND_ADVANTAGE_OZ_PRICES = [
4 => [4.75, 4.85, 4.90, 5.00, 5.05, 5.10, 5.15, 5.25, 5.25],
8 => [5.40, 5.50, 5.55, 5.60, 5.65, 5.70, 5.75, 5.85, 5.85],
12 => [6.15, 6.25, 6.30, 6.35, 6.40, 6.45, 6.55, 6.65, 6.65],
15.999 => [7.60, 7.75, 7.85, 8.00, 8.15, 8.25, 8.40, 8.55, 8.55]
];
const GROUND_ADVANTAGE_LB_PRICES = [
1 => [7.60, 7.75, 7.85, 8.00, 8.15, 8.25, 8.40, 8.55, 8.55],
2 => [8.50, 9.00, 9.55, 10.25, 11.00, 11.80, 12.90, 14.90, 14.90],
3 => [8.85, 9.50, 9.95, 10.80, 11.80, 12.90, 14.90, 17.65, 17.65],
4 => [9.55, 10.00, 10.70, 11.65, 12.85, 14.30, 16.35, 19.00, 19.00],
5 => [10.20, 10.65, 11.40, 12.45, 13.75, 15.40, 17.65, 20.50, 20.50],
6 => [10.60, 10.95, 11.75, 12.95, 14.55, 16.55, 19.25, 22.40, 22.40],
7 => [11.10, 11.40, 12.20, 13.55, 15.40, 17.80, 20.75, 24.25, 24.25],
8 => [11.55, 11.80, 12.55, 14.05, 16.20, 19.05, 22.60, 26.35, 26.35],
9 => [12.00, 12.25, 12.90, 14.55, 17.00, 20.30, 24.40, 28.40, 28.40],
10 => [12.70, 13.00, 13.70, 15.45, 18.15, 21.85, 26.55, 31.45, 31.45],
11 => [13.30, 13.75, 14.45, 16.30, 19.30, 23.40, 28.65, 34.55, 34.55],
12 => [13.90, 14.25, 14.90, 16.95, 20.25, 24.90, 30.85, 37.15, 37.15],
13 => [14.50, 14.80, 15.30, 17.40, 21.10, 26.35, 33.25, 40.70, 40.70],
14 => [15.10, 15.20, 15.75, 18.05, 22.20, 28.10, 35.85, 43.90, 43.90],
15 => [15.70, 15.85, 16.35, 18.60, 23.15, 29.30, 37.30, 45.90, 45.90],
16 => [16.30, 16.50, 16.95, 19.50, 24.10, 30.50, 38.75, 47.90, 47.90],
17 => [16.90, 17.10, 17.55, 20.35, 25.15, 31.90, 40.60, 50.30, 50.30],
18 => [17.50, 17.70, 18.15, 20.80, 26.20, 33.30, 42.45, 52.70, 52.70],
19 => [17.85, 18.10, 18.90, 21.20, 27.05, 34.15, 43.25, 54.40, 54.40],
20 => [18.20, 18.40, 19.60, 21.90, 28.15, 35.25, 44.40, 55.50, 55.50],
21 => [23.00, 23.45, 26.75, 29.70, 33.80, 44.85, 57.45, 69.10, 69.10],
22 => [23.80, 24.30, 28.15, 32.00, 35.90, 47.25, 58.65, 74.65, 74.65],
23 => [24.65, 25.10, 29.55, 34.55, 38.55, 48.70, 59.90, 75.45, 75.45],
24 => [25.50, 26.00, 31.05, 37.25, 40.40, 51.10, 61.20, 76.75, 76.75],
25 => [26.40, 26.95, 32.65, 40.25, 43.50, 53.55, 62.55, 81.25, 81.25],
26 => [28.40, 28.45, 34.40, 43.55, 53.35, 63.85, 74.15, 84.70, 84.70],
27 => [30.15, 30.20, 36.00, 45.00, 56.05, 66.70, 77.10, 87.75, 87.75],
28 => [31.10, 31.15, 36.50, 46.25, 57.55, 68.85, 79.85, 91.15, 91.15],
29 => [32.05, 32.15, 36.85, 47.35, 58.40, 70.20, 81.90, 93.65, 93.65],
30 => [33.00, 33.10, 37.45, 48.70, 59.20, 71.45, 83.40, 95.60, 95.60],
31 => [34.05, 34.10, 37.80, 51.25, 60.10, 72.80, 85.15, 97.80, 97.80],
32 => [34.40, 34.45, 38.60, 52.45, 60.65, 73.75, 86.50, 99.50, 99.50],
33 => [35.00, 35.05, 39.60, 53.80, 61.50, 74.95, 88.05, 101.50, 101.50],
34 => [35.30, 35.35, 40.65, 55.10, 62.70, 76.45, 89.85, 103.45, 103.45],
35 => [35.65, 35.75, 41.70, 55.80, 64.05, 77.90, 91.30, 105.00, 105.00],
36 => [36.05, 36.10, 42.90, 56.60, 65.60, 79.55, 93.05, 106.85, 106.85],
37 => [36.35, 36.45, 43.60, 57.45, 66.70, 80.85, 94.60, 108.65, 108.65],
38 => [36.80, 36.85, 44.75, 58.15, 68.00, 82.30, 96.15, 110.40, 110.40],
39 => [37.20, 37.30, 45.75, 58.90, 69.45, 83.80, 97.80, 112.10, 112.10],
40 => [37.65, 37.70, 46.75, 59.70, 70.90, 85.25, 99.25, 113.65, 113.65],
41 => [37.95, 38.00, 47.65, 60.40, 71.60, 86.35, 100.75, 115.45, 115.45],
42 => [38.20, 38.30, 48.50, 61.00, 73.05, 87.80, 102.15, 116.85, 116.85],
43 => [38.75, 38.80, 49.30, 61.55, 74.65, 89.25, 103.50, 118.10, 118.10],
44 => [39.00, 39.10, 50.15, 62.35, 76.20, 90.80, 105.05, 119.80, 119.80],
45 => [39.25, 39.35, 50.65, 62.75, 78.00, 92.50, 106.70, 121.20, 121.20],
46 => [39.55, 39.60, 51.00, 63.45, 79.35, 93.90, 108.10, 122.60, 122.60],
47 => [39.90, 40.00, 51.45, 64.05, 81.30, 95.65, 109.70, 124.00, 124.00],
48 => [40.30, 40.35, 51.95, 64.70, 82.80, 97.10, 111.00, 125.30, 125.30],
49 => [40.50, 40.55, 52.25, 65.15, 84.25, 98.55, 112.30, 126.50, 126.50],
50 => [40.65, 40.75, 52.55, 65.65, 85.95, 100.05, 113.75, 127.85, 127.85],
51 => [40.85, 40.95, 53.10, 66.20, 87.35, 101.50, 115.00, 129.05, 129.05],
52 => [41.40, 41.45, 53.40, 66.70, 88.05, 102.40, 116.25, 130.50, 130.50],
53 => [42.10, 42.15, 53.80, 67.10, 88.75, 103.35, 117.55, 132.20, 132.20],
54 => [42.60, 42.70, 54.00, 67.55, 89.45, 104.55, 119.05, 134.05, 134.05],
55 => [43.35, 43.45, 54.35, 67.95, 90.10, 105.50, 120.40, 135.80, 135.80],
56 => [43.95, 44.00, 54.75, 68.35, 90.70, 106.40, 121.55, 137.15, 137.15],
57 => [44.65, 44.70, 54.90, 68.70, 91.20, 107.05, 122.30, 138.10, 138.10],
58 => [45.30, 45.40, 55.15, 69.20, 91.90, 107.95, 123.45, 139.30, 139.30],
59 => [46.00, 46.10, 55.45, 69.50, 92.40, 108.55, 124.25, 140.30, 140.30],
60 => [46.65, 46.75, 55.65, 70.20, 92.85, 109.15, 124.95, 141.20, 141.20],
61 => [47.35, 47.40, 55.95, 71.45, 93.35, 110.20, 126.45, 143.15, 143.15],
62 => [47.80, 47.90, 56.05, 72.35, 93.90, 111.30, 128.15, 145.50, 145.50],
63 => [48.75, 48.85, 56.35, 73.55, 94.30, 112.35, 129.85, 147.80, 147.80],
64 => [49.25, 49.35, 58.10, 74.60, 94.80, 113.50, 131.50, 150.10, 150.10],
65 => [49.95, 50.00, 58.25, 75.65, 95.00, 114.35, 133.15, 152.30, 152.30],
66 => [50.55, 50.65, 58.45, 76.85, 95.55, 115.55, 134.85, 154.70, 154.70],
67 => [51.35, 51.45, 58.55, 78.20, 95.90, 116.40, 136.35, 156.65, 156.65],
68 => [52.00, 52.10, 58.70, 79.10, 96.10, 117.10, 137.50, 158.30, 158.30],
69 => [52.65, 52.75, 58.75, 80.10, 96.35, 117.75, 138.70, 160.00, 160.00],
70 => [53.25, 53.35, 58.95, 81.45, 96.65, 118.55, 139.95, 161.75, 161.75],
"OVERSIZE" => [89.05, 91.55, 113.40, 137.75, 161.90, 186.15, 209.50, 233.75, 233.75]
];
const PRIORITY_PRICES = [
1 => [9.35, 9.55, 9.85, 10.20, 10.65, 10.95, 11.75, 12.55, 21.35],
2 => [9.80, 10.05, 10.55, 11.45, 12.45, 13.40, 15.60, 17.05, 33.85],
3 => [10.45, 10.75, 11.35, 12.55, 14.50, 16.30, 18.95, 22.45, 45.25],
4 => [11.15, 11.45, 12.20, 13.30, 15.80, 19.35, 22.85, 25.45, 52.40],
5 => [11.90, 12.20, 13.05, 14.05, 16.65, 21.55, 26.25, 29.35, 60.65],
6 => [12.30, 12.60, 13.45, 14.85, 17.85, 24.05, 29.30, 33.05, 68.50],
7 => [12.80, 13.15, 13.95, 15.75, 19.55, 25.85, 32.75, 37.20, 77.00],
8 => [13.35, 13.70, 14.65, 16.15, 20.60, 27.50, 36.45, 41.60, 86.15],
9 => [13.60, 13.95, 15.05, 16.55, 22.15, 29.90, 39.50, 45.10, 95.85],
10 => [14.90, 15.25, 16.05, 17.90, 23.50, 32.25, 42.85, 49.00, 104.50],
11 => [15.95, 16.30, 16.95, 19.00, 24.45, 34.80, 46.50, 53.15, 115.60],
12 => [16.65, 17.05, 17.70, 19.65, 25.80, 36.90, 50.40, 57.65, 124.10],
13 => [17.25, 17.70, 18.40, 20.35, 27.30, 38.90, 54.70, 62.60, 128.55],
14 => [18.00, 18.45, 19.20, 21.10, 28.80, 41.45, 59.35, 67.85, 134.95],
15 => [18.75, 19.20, 20.05, 21.80, 30.40, 42.75, 60.80, 69.60, 138.80],
16 => [19.50, 20.00, 21.10, 22.90, 32.35, 44.80, 64.05, 73.50, 146.40],
17 => [20.35, 20.85, 22.20, 24.10, 34.50, 47.30, 67.45, 77.35, 154.20],
18 => [21.25, 21.80, 23.35, 25.30, 36.70, 49.35, 70.75, 81.30, 162.05],
19 => [22.20, 22.75, 24.55, 26.55, 39.10, 50.80, 72.30, 83.00, 169.70],
20 => [23.15, 23.75, 25.85, 27.95, 41.65, 53.00, 74.85, 86.85, 177.55],
21 => [24.00, 24.60, 27.20, 30.10, 43.95, 56.05, 76.70, 89.35, 183.05],
22 => [24.85, 25.45, 28.55, 32.45, 46.45, 59.35, 78.65, 91.90, 187.60],
23 => [25.70, 26.35, 30.00, 35.05, 49.05, 62.75, 80.65, 94.50, 190.85],
24 => [26.60, 27.25, 31.50, 37.75, 51.80, 66.40, 82.70, 97.20, 195.60],
25 => [27.55, 28.25, 33.10, 40.75, 54.70, 70.20, 84.80, 99.95, 198.75],
26 => [29.35, 30.50, 34.80, 43.95, 58.30, 74.95, 88.45, 103.00, 205.10],
27 => [31.00, 32.20, 36.40, 45.45, 60.25, 76.00, 90.65, 106.80, 212.80],
28 => [31.85, 33.05, 36.90, 46.65, 62.20, 77.05, 92.85, 111.05, 220.85],
29 => [32.60, 33.85, 37.25, 47.80, 63.70, 78.40, 95.05, 114.20, 226.75],
30 => [33.40, 34.70, 37.85, 49.15, 65.65, 80.65, 97.20, 116.70, 231.75],
31 => [34.25, 35.55, 38.25, 51.70, 67.45, 81.85, 99.40, 119.40, 238.25],
32 => [34.70, 36.05, 39.05, 52.90, 71.00, 82.95, 101.60, 121.55, 243.15],
33 => [35.40, 36.75, 40.05, 54.25, 71.95, 84.55, 103.65, 123.80, 247.80],
34 => [35.85, 37.25, 41.10, 55.60, 73.55, 86.50, 105.85, 126.20, 252.30],
35 => [36.40, 37.80, 42.15, 56.30, 75.10, 88.80, 107.90, 128.20, 256.50],
36 => [37.00, 38.40, 43.35, 57.10, 76.65, 91.15, 109.40, 130.50, 261.00],
37 => [37.40, 38.85, 44.05, 57.95, 78.05, 93.50, 110.80, 132.60, 265.25],
38 => [38.05, 39.50, 45.25, 58.65, 79.55, 96.10, 112.15, 134.75, 269.55],
39 => [38.55, 40.05, 46.25, 59.40, 81.20, 98.40, 115.10, 136.75, 273.65],
40 => [39.15, 40.65, 47.20, 60.20, 83.05, 99.95, 117.65, 138.75, 277.40],
41 => [39.65, 41.15, 48.10, 60.90, 83.80, 101.60, 120.15, 140.75, 283.65],
42 => [40.00, 41.55, 48.95, 61.50, 85.55, 103.40, 121.70, 142.60, 287.60],
43 => [40.60, 42.15, 49.75, 62.05, 87.50, 105.90, 123.30, 144.40, 291.10],
44 => [41.00, 42.60, 50.60, 62.85, 89.30, 107.60, 124.70, 146.10, 294.70],
45 => [41.35, 42.95, 51.15, 63.30, 91.30, 108.80, 126.10, 147.95, 298.40],
46 => [41.65, 43.25, 51.50, 63.95, 92.95, 109.95, 127.45, 149.75, 301.95],
47 => [42.00, 43.60, 51.95, 64.55, 95.10, 111.20, 128.85, 151.40, 305.20],
48 => [42.40, 44.05, 52.45, 65.20, 96.90, 112.60, 130.10, 153.00, 308.55],
49 => [42.60, 44.25, 52.75, 65.70, 98.75, 114.10, 131.45, 154.60, 311.65],
50 => [42.85, 44.50, 53.10, 66.15, 100.65, 115.60, 133.20, 156.10, 314.90],
51 => [43.15, 44.80, 53.60, 66.75, 101.90, 117.25, 135.15, 157.60, 320.20],
52 => [43.60, 45.25, 53.95, 67.25, 103.15, 118.50, 137.10, 159.40, 324.25],
53 => [44.15, 45.85, 54.30, 67.60, 104.00, 119.50, 139.25, 161.55, 328.40],
54 => [44.60, 46.30, 54.50, 68.10, 104.90, 120.30, 141.40, 163.80, 332.95],
55 => [45.20, 46.95, 54.90, 68.45, 105.65, 121.20, 143.60, 165.95, 337.35],
56 => [45.70, 47.45, 55.25, 68.90, 106.30, 122.15, 145.60, 167.50, 340.55],
57 => [46.25, 48.05, 55.45, 69.25, 106.90, 123.00, 147.85, 168.80, 343.00],
58 => [46.80, 48.60, 55.70, 69.75, 107.65, 123.65, 149.90, 170.10, 345.50],
59 => [47.35, 49.15, 55.95, 70.05, 108.35, 124.40, 150.75, 171.40, 348.30],
60 => [47.85, 49.70, 56.20, 70.75, 108.85, 125.05, 151.60, 172.50, 350.55],
61 => [48.45, 50.30, 56.50, 72.00, 109.40, 125.75, 152.50, 174.85, 355.45],
62 => [48.80, 50.65, 56.60, 72.90, 110.00, 126.40, 153.25, 177.65, 361.00],
63 => [49.55, 51.45, 56.85, 74.10, 110.50, 127.05, 153.90, 180.50, 366.90],
64 => [50.30, 52.25, 58.65, 75.20, 110.95, 127.55, 154.70, 183.15, 372.40],
65 => [50.85, 52.80, 58.80, 76.20, 111.40, 128.05, 155.40, 186.15, 378.35],
66 => [51.40, 53.35, 59.00, 77.45, 111.95, 128.65, 155.95, 188.70, 383.75],
67 => [51.95, 53.95, 59.10, 78.75, 112.25, 128.95, 156.55, 191.30, 388.75],
68 => [52.45, 54.45, 59.20, 79.65, 112.50, 130.65, 157.15, 193.30, 393.00],
69 => [52.85, 54.90, 59.25, 80.70, 112.90, 132.20, 157.60, 195.40, 397.10],
70 => [53.40, 55.45, 59.50, 82.00, 113.25, 133.85, 158.10, 196.75, 401.35]
];
}