Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Nerdmonkey

Organização de itens em caixas para cálculo de frete nos Correios

Recommended Posts

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;
    }
}

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Está lá em cima. Nas constantes. Solução, até onde pesquisei, nada simples.

Mas como não desisto fácil... bora continuar tentando :pensive:

Compartilhar este post


Link para o post
Compartilhar em outros sites

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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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. :sweat_smile:

Compartilhar este post


Link para o post
Compartilhar em outros sites
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, A*C*L, que no caso daria 157500 (25*70*90), como você extrai o valor final das caixas com esse resultado?

Compartilhar este post


Link para o post
Compartilhar em outros sites
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.

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

Compartilhar este post


Link para o post
Compartilhar em outros sites

  • Conteúdo Similar

    • Por violin101
      Caros amigos, saudações.
       
      Por favor, poderiam me ajudar.

      Estou com a seguinte dúvida:
      --> como faço para para implementar o input código do produto, para quando o usuário digitar o ID o sistema espera de 1s a 2s, sem ter que pressionar a tecla ENTER.

      exemplo:
      código   ----   descrição
           1       -----   produto_A
       
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Humildemente peço desculpa por postar uma dúvida que tenho.

      Preciso salvar no MySql, os seguinte Registro:

      1 - Principal
      ====> minha dúvida começa aqui
      ==========> como faço para o Sistema Contar Automaticamente o que estiver despois do 1.____?
      1.01 - Matriz
      1.01.0001 - Estoque
      1.01.0002 - Oficina
      etc

      2 - Secundário
      2.01 - Loja_1
      2.01.0001 - Caixa
      2.01.0002 - Recepção
      etc
       
      Resumindo seria como se fosse um Cadastro de PLANO de CONTAS CONTÁBEIL.

      Grato,


      Cesar









       
    • Por violin101
      Caros amigos, saudações.

      Por favor, me perdoa em recorrer a orientação dos amigos.

      Preciso fazer um Relatório onde o usuário pode Gerar uma Lista com prazo para vencimento de: 15 / 20/ 30 dias da data atual.

      Tem como montar uma SQL para o sistema fazer uma busca no MySql por período ou dias próximo ao vencimento ?

      Tentei fazer assim, mas o SQL me traz tudo:
      $query = "SELECT faturamento.*, DATE_ADD(faturamento.dataVencimento, INTERVAL 30 DAY), fornecedor.* FROM faturamento INNER JOIN fornecedor ON fornecedor.idfornecedor = faturamento.id_fornecedor WHERE faturamento.statusFatur = 1 ORDER BY faturamento.idFaturamento $ordenar ";  
      Grato,
       
      Cesar
       
       
       
       
    • Por violin101
      Caros amigos, saudações
       
      Por favor, me perdoa em recorrer a orientação dos amigos, tenho uma dúvida.
       
      Gostaria de uma rotina onde o Sistema possa acusar para o usuário antes dos 30 dias, grifar na Tabela o aviso de vencimento próximo, por exemplo:
       
      Data Atual: 15/11/2024
                                           Vencimento
      Fornecedor.....................Data.....................Valor
      Fornecedor_1...........01/12/2024..........R$ 120,00 <== grifar a linha de Laranja
      Fornecedor_1...........01/01/2025..........R$ 130,00
      Fornecedor_2...........15/12/2024..........R$ 200,00 <== grifar a linha de Amarelo
      Fornecedor_2...........15/01/2025..........R$ 230,00
      Fornecedor_3...........20/12/2024..........R$ 150,00
       
      Alguém tem alguma dica ou leitura sobre este assunto ?

      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.

      Por favor, me perdoa em recorrer a ajuda dos amigos, mas preciso entender uma processo que não estou conseguindo sucesso.

      Como mencionado no Título estou escrevendo um Sistema Web para Gerenciamento de Empresa.
       
      Minha dúvida, que preciso muito entender:
      - preciso agora escrever a Rotina para Emissão de NFe e essa parte não estou conseguindo.
       
      tenho assistido alguns vídeos e leituras, mas não estou conseguindo sucesso, já fiz toda as importações das LIB da NFePhp conforme orientação.

      Preciso de ajuda.

      Algum dos amigos tem conhecimento de algum passo-a-passo explicando a criação dessa rotina ?

      tenho visto alguns vídeos com LARAVEL, mas quando tento utilizar e converter para PHP+Codeiginter, dá uma fila de erros que não entendo, mesmo informando as lib necessárias.

      Alguns do amigo tem algum vídeo, leitura explicando essa parte ?

      Grato,

      Cesar.
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.