Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
A quanto tempo não posto aqui. As novidades do fórum estão bem bacanas... já volto com uma bomba rs
Estou adaptando um classe para arranjar os produtos do carrinho de um e-comerce em caixas para calcular o frete juntos aos correios.
Gostaria de sugestões dos colegas para implementar, sempre que um caixa atingir o limite, gerar uma nova caixa... a parte da comunicação com a API do correios está bem tranquilo.
O que tá pegando mesmo é essa parte da organização dos itens em várias caixas.
Vou deixar aqui o código completo que estou testando...
/
config.php
<?php
define("MIN_LARGURA", 11);
define("MAX_LARGURA", 105);
define("MIN_ALTURA", 2);
define("MAX_ALTURA", 105);
define("MIN_COMPRIMENTO", 16);
define("MAX_COMPRIMENTO", 105);
define("MIN_SOMA_CLA", 29);
define("MAX_SOMA_CLA", 200);
function dd($data) {
echo '<pre>';
var_dump($data);
echo '</pre>';
}
index.php
<?php
require_once 'config.php';
require_once 'Boxes.php';
$cart = [
[
'title' => 'Book - The art of war',
'A' => 25,
'L' => 70,
'C' => 90,
],
[
'title' => 'Book - The art of war',
'A' => 25,
'L' => 70,
'C' => 90,
],
[
'title' => 'Book - The art of war',
'A' => 25,
'L' => 70,
'C' => 90,
],
];
$boxes = new Boxes($cart);
dd($boxes->createBoxes());
Boxes.php
<?php
class Boxes {
private $cart = [];
private $box = [];
private $box_properties = [];
/**
* __construct
*
* @param array $cart
*/
public function __construct($cart = [])
{
$this->cart = $cart;
$this->box_properties = [
'altura' => 0,
'largura' => 0,
'comprimento' => 0,
'qtd_itens' => 0,
'message' => null,
'volume' => 0,
'volume_itens' => 0,
'volume_vazio' => 0,
'comprimento_remanescente' => 0,
'largura_remanescente' => 0,
'altura_remanescente' => 0
];
}
/**
* Order items inside the box
*
* @return array
*/
public function orderBox()
{
foreach ($this->cart as $k => $item):
$new_height = min($item['A'], $item['L'], $item['C']);
$new_length = max($item['A'], $item['L'], $item['C']);
$width = [$item['A'], $item['L'], $item['C']];
sort($width) ;
array_shift($width);
array_pop($width);
$item['L'] = isset($width[0]) ? $width[0] : $new_height;
$item['A'] = $new_height ;
$item['C'] = $new_length ;
$item['LC'] = $item['L'] * $item['C'] ;
$this->cart[$k] = $item;
endforeach;
usort($this->cart, function($a, $b){
return $a['LC'] < $b['LC'];
});
return $this->cart ;
}
/**
* Create and put items inside the box
*
* @return array
*/
public function createBoxes()
{
$this->cart = $this->orderBox();
$this->box = json_decode(json_encode($this->box_properties,FALSE));
$this->organizeItems();
$this->box->volume = ($this->box->altura * $this->box->largura * $this->box->comprimento);
$this->box->volume_vazio = $this->box->volume - $this->box->volume_itens;
$this->minSpecifications();
$this->errors();
return $this->box;
}
private function organizeItems()
{
foreach ($this->cart as $item):
$this->box->qtd_itens++;
$this->box->volume_itens += ($item['A'] * $item['L'] * $item['C']);
$this->allocateItems($item);
$this->box->altura += $item['A'];
if($item['L'] > $this->box->largura):
$this->box->largura = $item['L'];
endif;
if ($item['C'] > $this->box->comprimento):
$this->box->comprimento = $item['C'];
endif;
$this->box->comprimento_remanescente = $this->box->comprimento;
$this->box->largura_remanescente = $this->box->largura - $item['L'];
$this->box->altura_remanescente = $item['A'];
endforeach;
}
private function allocateItems($item)
{
if($this->box->comprimento_remanescente >= $item['C'] && $this->box->largura_remanescente >= $item['L']):
if($item['A'] > $this->box->altura_remanescente):
$this->box->altura += $item['A'] - $this->box->altura_remanescente ;
endif;
if($item['C'] > $this->box->comprimento):
$this->box->comprimento = $item['C'];
endif;
$this->box->comprimento_remanescente = $this->box->comprimento - $item['C'];
$this->box->largura_remanescente = $this->box->largura_remanescente - $item['L'] ;
$this->box->altura_remanescente = $item['A'] > $this->box->altura_remanescente ? $item['A'] : $this->box->altura_remanescente ;
endif;
}
private function minSpecifications()
{
if($this->box->altura > 0 && $this->box->altura < MIN_ALTURA):
$this->box->altura = MIN_ALTURA ;
endif;
if($this->box->largura > 0 && $this->box->largura < MIN_LARGURA):
$this->box->largura = MIN_LARGURA ;
endif;
if($this->box->comprimento > 0 && $this->box->comprimento < MIN_COMPRIMENTO):
$this->box->comprimento = MIN_COMPRIMENTO ;
endif;
}
private function errors()
{
if($this->box->altura > MAX_ALTURA):
$this->box->message = "Erro: Altura maior que o permitido.";
endif;
if($this->box->largura > MAX_LARGURA ):
$this->box->message = "Erro: Largura maior que o permitido.";
endif;
if($this->box->comprimento > MAX_COMPRIMENTO ):
$this->box->message = "Erro: Comprimento maior que o permitido.";
endif;
if(($this->box->comprimento + $this->box->comprimento + $this->box->comprimento) < MIN_SOMA_CLA):
$this->box->message = "Erro: Soma dos valores C+L+A menor que o permitido.";
endif;
if(($this->box->comprimento + $this->box->comprimento + $this->box->comprimento) > MAX_SOMA_CLA):
$this->box->message = "Erro: Soma dos valores C+L+A maior que o permitido.";
endif;
}
}Está lá em cima. Nas constantes. Solução, até onde pesquisei, nada simples.
Mas como não desisto fácil... bora continuar tentando
A ideia talvez seria aplicar um método quase no mesmo estilo que você fez no método errors(), só que ao invés de disparar um erro, você abriria uma nova caixa caso o cliente fosse adicionando mais itens no carrinho.
Qual ideia você teve que não é simples? De repente se você colocar ela aqui a galera pode ajudar a simplificar ou dar novas ideias.
A justificativa do meu argumento de não ser tão simples de resolver esse problema https://pt.wikipedia.org/wiki/Problema_da_mochila. Fora o fato de que ninguém, pelo menos que eu conheça, como programador, tenha feito parecido ou consiga palpitar sobre um caminha por onde seguir. Mas já imaginava que não seria fácil antes mesmo de começar. Dinamismo, de certa forma, na minha opinião, torna o código reutilizável, e de certa forma, aumenta sua complexabilidade de desenvolvimento, para soluções bem elaboradas.
A sua ideia é boa, estou realmente trabalhando em cima disso atualmente. A lógica é verificar quando uma caixa atingiu seu limite > fechar esta caixa, tendo seus parâmetros para medir a cubagem definidos(A C L) > abrir uma nova caixa e começar a alocar os itens que não foram alocados na caixa anterior, pois excederiam os limites especificados pelos Correios.
Isso me daria margem para definir o valor do frete com base na cubagem de cada caixa. Posso ter 'n' caixas, cada uma com 'm' volume e peso distintos. Bem complexo, pelo menos pra mim, no momento. Mas acredito que não é impossível.
>
8 horas atrás, Nerdmonkey disse:
A sua ideia é boa, estou realmente trabalhando em cima disso atualmente. A lógica é verificar quando uma caixa atingiu seu limite > fechar esta caixa, tendo seus parâmetros para medir a cubagem definidos(A C L) > abrir uma nova caixa e começar a alocar os itens que não foram alocados na caixa anterior, pois excederiam os limites especificados pelos Correios.
Isso me daria margem para definir o valor do frete com base na cubagem de cada caixa. Posso ter 'n' caixas, cada uma com 'm' volume e peso distintos. Bem complexo, pelo menos pra mim, no momento. Mas acredito que não é impossível.
Perfeito, a lógica ta bacana, vai verificando cada produto que entra, e eu acho que aquele método errors() que você fez é quase que meio caminho andado, pq pelo o que eu entendi ele verifica o tamanho das caixas e dispara os erros informando que tal largura/altura/comprimento da caixa foi excedido, só que, caso o cliente já esteja com a caixa cheia ou quase cheia e queira continuar comprando e o produto que ele adicionar não caber na caixa atual, chama um método tipo "newBox()", bota a caixa que já está cheia em um array nesse método e guarda ele, deixa o cliente continuar comprando e abrindo novas caixas se necessário.
Eu só não consigo te ajudar mais precisamente pq, sinceramente, eu não manjo muito do cálculo que é feito pra definir o tamanho/volume de uma caixa, pq pelo o que você falou você ta multiplicando todos eles, ACL, que no caso daria 157500 (257090), como você extrai o valor final das caixas com esse resultado?
>
Citar
Perfeito, a lógica ta bacana, vai verificando cada produto que entra, e eu acho que aquele método errors() que você fez é quase que meio caminho andado...
Estou trabalhando nisso. A lógica aqui é verificar quando a caixa exceder altura, largura ou comprimento. Normalmente, vai exceder em altura, porque os produtos são pequenos, ai na organização, consigo ir colocado os maiores por baixo e ir ajustando os demais no espaço remanescente.
>
Citar
como você extrai o valor final das caixas com esse resultado?
É nessa questão mesmo que estou testando uma possível solução. Mas o conceito você pegou bem. É gerar a caixa, quando bater no limite, eu fecho a caixa e começo uma nova. Estou testando algumas formas de aplicar isso na classe. O trabalhoso está sendo armazenas os itens que cabem na caixa. Guardá-los e fechar a caixa. Pegar somente o que passa e ir colocando em novas caixas conforme a quantidade.
Pensei em uma solução bem elegante e que se aproximaria bem do tamanho da embalagem necessária para trasnportar os produtos.
Você precisa inicialmente calcular o cm³ (centimetro cúbico = multiplicar a altura, com a largura, com o comprimento) encontrando o volume que o produto ocupa. Apos fazer isso com cada produto, você soma os volumes e depois calcula a raiz cúbica desse valor, o resultado dessa raiz cúbica será cada uma das medidas da sua embalagem (altura, comprimento e largura) sempre gerará uma embalagem quadrada, mas não importa, pois isso irá aproximar bem o valor do frete real. Caso ultrapasse a medida máxima permitida pelos correios, basta dividir em mais caixas e somar os fretes
Como que é definido o limite da caixa?