After some time reading a lot online material and thoroughly researching the subject, I think I have managed to come up with a satisfactory result.
As I've discussed here (and also a meta-related question) I know that 2D or 3D packaging is going to be extremely difficult (or impossible), but, as stated in the question, my biggest question was how to calculate the freight for one or more products so that one of the following proposals is not made:
- Sum of
Frete A
+ Frete B
;
- Sum of measures of
Produto A
+ Produto B
and freight calculation;
Another problem encountered was how to add the information of several products, with the webservice
of the Post Office accepting only one value for each of the fields.
In this way I have been able to arrive at a calculation where, to date, I believe that you are returning values much closer to the actual values of the freight than with the previously used method.
Note: I did not officially test the code by checking the post office at the time of sending the product.
The logic behind the calculation is as follows:
- Calculate the value in
cm³
for each product (Width x Height x Length x Quantity);
- Add the value of
cm³
and weight of all products;
- Extraction of the cubic root from the sum of% with% of all products;
For these calculations, I'm using this code:
$total_peso = 0;
$total_cm_cubico = 0;
/**
* $produto = lista de produtos no carrinho de compras. Deve possuir,
* obrigatoriamente, os campos largura, altura, comprimento e quantidade.
*/
foreach ($produto as $row) {
$row_peso = $row['peso'] * $row['quantidade'];
$row_cm = ($row['altura'] * $row['largura'] * $row['comprimento']) * $row['quantidade'];
$total_peso += $row_peso;
$total_cm_cubico += $row_cm;
}
$raiz_cubica = round(pow($total_cm_cubico, 1/3), 2);
$resposta = array(
'total_peso' => $total_peso,
'raiz_cubica' => $raiz_cubica,
);
In this way, when filling in the data to be sent to the Post Office, I fill in the following way:
// Os valores 16, 2, 11 e 0.3 são os valores mínimos determinados pelo serviço dos Correios
$comprimento = $raiz_cubica < 16 ? 16 : $raiz_cubica;
$altura = $raiz_cubica < 2 ? 2 : $raiz_cubica;
$largura = $raiz_cubica < 11 ? 11 : $raiz_cubica;
$peso = $total_peso < 0.3 ? 0.3 : $total_peso;
$diametro = hypot($comprimento, $largura); // Calculando a hipotenusa pois minhas encomendas são retangulares
'nVlPeso' => $peso,
'nVlComprimento' => $comprimento,
'nVlAltura' => $altura,
'nVlLargura' => $largura,
'nVlDiametro' => $diametro, // não obrigatório
With this calculation I was able to achieve results where calculating the individual freight value of 2 products I got the values:
- Product A: R $ 17.10
- Product B: R $ 20.40
And when I made the two products together, I got R $ 23.60 (considering that by the measures and type of package I did not get a value lower than R $ 17.10 - it should be a minimal fee).
This type of result was repeated (similarly) in several different products and different quantities, that is, there was no freight sum but a gradual increase according to the measurements and weight of the products.
Remembering that there are some outstanding features, such as validating the measurements so that they do not exceed the maximum values and, if you exceed, divide the freight into more than one "box".