Página 1 de 4

[TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 25 Out 2011, 09:53
por rgtobr
Para quem está com problemas de fazer os produtos voltarem ao estoque após um pedido ser cancelado na versão 1.5.1.3, a solução pode ser mais simples do que parece. Já existe um código escrito para resolver este problema, porém, ele está dentro de uma condição ainda não definida nas configurações do sistema. Entretanto, é possível desativar essa condição para que o código seja executado e, assim que o pedido é removido os produtos retornam ao estoque.

O código que repõe o estoque é executado somente quando o pedido é removido (deletado) e não quando é adicionado a opção "Cancelado" no status do pedido.

Segue a solução:

1. edite o arquivo /admin/model/sale/order.php e procure por:
public function deleteOrder($order_id) {

2. comente o if adicionando duas barras na frente das linhas abaixo:
if ($this->config->get('config_stock_subtract')) {
}
... desta forma:
// if ($this->config->get('config_stock_subtract')) {
// }

3. ficará assim:
Código: Selecionar todos
	public function deleteOrder($order_id) {
		//if ($this->config->get('config_stock_subtract')) {
			$order_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0' AND order_id = '" . (int)$order_id . "'");

			if ($order_query->num_rows) {
				$product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");

				foreach($product_query->rows as $product) {
					$this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_id = '" . (int)$product['product_id'] . "'");

					$option_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "' AND order_product_id = '" . (int)$product['order_product_id'] . "'");

					foreach ($option_query->rows as $option) {
						$this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_option_value_id = '" . (int)$option['product_option_value_id'] . "' AND subtract = '1'");
					}
				}
			}
		//}

		$this->db->query("DELETE FROM `" . DB_PREFIX . "order` WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_history WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "'");
	  	$this->db->query("DELETE FROM " . DB_PREFIX . "order_download WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_total WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "customer_transaction WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "customer_reward WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "affiliate_transaction WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "coupon_history WHERE order_id = '" . (int)$order_id . "'");
	}
Espero ter ajudado.

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 25 Out 2011, 11:56
por Manoel Vidal
Parabéns pela contribuição, tenho certeza que vai ajudar muitos :D

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 24 Nov 2011, 09:28
por MMaat
Perfeito!
Parabéns pela contribuição. :D

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 28 Nov 2011, 04:58
por Renato Frota
Retirar essa checagem funciona, mas o ideal é verificar se o produto havia sido inicialmente removido do estoque (os produtos possuem uma opção "subtrair do estoque?").

Eu corrigi a função e otimizei os SELECT, testem aí (essas são só as linhas 130 a 147 da função, as últimas eu não copiei, já que não foram alteradas):
Código: Selecionar todos
	public function deleteOrder($order_id) {
		$order_query = $this->db->query("SELECT order_id FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0' AND order_id = '" . (int)$order_id . "'");
		if ($order_query->num_rows) {
			$product_query = $this->db->query("SELECT product_id,quantity,order_product_id FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");
			foreach($product_query->rows as $product) {
				$readd_query = $this->db->query("SELECT subtract FROM " . DB_PREFIX . "product WHERE product_id = '" . (int)$product['product_id'] . "'");
				if ($readd_query->num_rows) {
					$readd_value = $readd_query->row['subtract'];
					if ($readd_value) {
						$this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_id = '" . (int)$product['product_id'] . "'");
						$option_query = $this->db->query("SELECT product_option_value_id FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "' AND order_product_id = '" . (int)$product['order_product_id'] . "'");
						foreach ($option_query->rows as $option) {
							$readd_option_query = $this->db->query("SELECT subtract FROM " . DB_PREFIX . "product_option_value WHERE product_option_value_id = '" . (int)$option['product_option_value_id'] . "'");
							if ($readd_option_query->num_rows) {
								$readd_option_value = $readd_option_query->['subtract'];
								if ($readd_option_value) {
									$this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_option_value_id = '" . (int)$option['product_option_value_id'] . "' AND subtract = '1'");
								}
							}
						}
					}
				}
			}
		}
-- editado --

o Daniel acabou de atualizar esse arquivo na SVN, é praticamente a minha função re-escrita... ele foi mais inteligente nas cláusulas WHERE. Mas estou sem dormir desde ontem, mereço um desconto! rsrs.

A função completa ficou assim:
Código: Selecionar todos
	public function deleteOrder($order_id) {
		$order_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0' AND order_id = '" . (int)$order_id . "'");

		if ($order_query->num_rows) {
			$product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");

			foreach($product_query->rows as $product) {
				$this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_id = '" . (int)$product['product_id'] . "' AND subtract = '1'");

				$option_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "' AND order_product_id = '" . (int)$product['order_product_id'] . "'");

				foreach ($option_query->rows as $option) {
					$this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_option_value_id = '" . (int)$option['product_option_value_id'] . "' AND subtract = '1'");
				}
			}
		}

		$this->db->query("DELETE FROM `" . DB_PREFIX . "order` WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_download WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "order_history WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");
      	$this->db->query("DELETE FROM " . DB_PREFIX . "order_total WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "customer_transaction WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "customer_reward WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "affiliate_transaction WHERE order_id = '" . (int)$order_id . "'");
		$this->db->query("DELETE FROM " . DB_PREFIX . "coupon_history WHERE order_id = '" . (int)$order_id . "'");
	}
O mais engraçado foi quando eu perguntei "porque você usa sempre SELECT * FROM se precisa de apenas 1, 2 ou 3 colunas em cada consulta?"...

A resposta foi simplesmente: lazyness (preguiça). :?

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 12 Dez 2011, 19:11
por lyon
Olá pessoal,

Tentei fazer as mudanças informadas no tópico.
Quando eu cancelo o pedido, o produto não volta ao estoque.

Alguém poderia ajudar?

Grato

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 12 Dez 2011, 22:10
por Renato Frota
lyon escreveu:Olá pessoal,

Tentei fazer as mudanças informadas no tópico.
Quando eu cancelo o pedido, o produto não volta ao estoque.

Alguém poderia ajudar?

Grato
Só volta quando é DELETADO.

E você seguiu as instruções do meu último CODE? São as alterações oficiais que serão implementadas na 1.5.2.

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 12 Dez 2011, 22:20
por lyon
Olá Renato,

Fiz todas as alterações mostradas acima.

1º - Comentei a linha do if. Não funcionou e voltei ao normal.
2º - Copiei a parte do código que vc colocou. Não funcionou e voltei ao normal.
3º - Copiei a função inteira e também não funcionou. Ai voltei ao normal.

Até pensei que pudesse ser a forma que estou fechando a venda, mas creio que não.

Fechar venda.

Clique no visualizar o pedido -> histórico -> altero pra cancelado -> adicionar histórico.

É isso neh?... rsss

Abs!

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 12 Dez 2011, 22:56
por Renato Frota
Não. Tem que deletar o pedido. Só marcar cancelado não retorna o estoque.

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 12 Dez 2011, 23:02
por lyon
Entendi Renato. Só acho estranho isso... rsss
Me diz uma coisa, os pedidos excluidos aparecem em relatório?
Pergunto isso pois meus relatórios não estão apresentando nada.

Abs!

Re: [TUTORIAL] Retornar estoque ao deletar pedido v1.5.1.3

Enviado: 14 Dez 2011, 12:59
por rgtobr
Pessoal, vejo que tem muita gente batendo a cabeça aí por causa da reposição do produto em estoque.

No início eu disse que é possível fazer os produtos voltarem ao estoque ao excluir o pedido, sim, basta fazer os ajustes que comentei. Vejo que vocês estão tendo a necessidade de reabastecer o estoque somente ao adicionar no histórico do pedido a situação CANCELADO, correto?

Então segue a solução:

1. edite o arquivo /admin/model/sale/order.php

2. procure pelo comentário // Send out any gift voucher mails por volta da linha 490, este comentário fica dentro da function addOrderHistory, então adicione o código abaixo uma linha acima deste comentário:
Código: Selecionar todos
        // Retorna ao estoque se cancelado (verificar a tabela ORDER_STATUS se o item CANCELED é número 7 e mudar na linha abaixo este número se necessário)
		if ((int)$data['order_status_id'] == 7) {
			$order_query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE order_status_id > '0' AND order_id = '" . (int)$order_id . "'");

			if ($order_query->num_rows) {
				$product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int)$order_id . "'");

				foreach($product_query->rows as $product) {
					$this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_id = '" . (int)$product['product_id'] . "'");

					$option_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_option WHERE order_id = '" . (int)$order_id . "' AND order_product_id = '" . (int)$product['order_product_id'] . "'");

					foreach ($option_query->rows as $option) {
						$this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET quantity = (quantity + " . (int)$product['quantity'] . ") WHERE product_option_value_id = '" . (int)$option['product_option_value_id'] . "' AND subtract = '1'");
					}
				}
			}
		}
* se precisarem que os produtos retornem ao estoque em outras situações além do CANCELADO, modifique a condição "if" ajustando-a para as suas necessidades

Espero ter ajudado mais uma vez.


*************************************

OBSERVAÇÃO IMPORTANTE: caso utilize este recurso com o módulo da MoIP, cuidado com as mensagens de retorno automático que retornam o status "cancelado", pois, se a MoIP retornar o status de "cancelado" mais de uma vez, é provável que os produtos sejam adicionados várias vezes. Portanto, se isto ocorrer, edite o arquivo retorno_moip.php, no final há o código abaixo:

Código: Selecionar todos
	if (isset($errors)){
	  header("HTTP 200");
	} else {
	  header("HTTP 500");
	}
Então substitua essas linhas por:
Código: Selecionar todos
	  header("HTTP 200");
... até que alguém encontre uma solução melhor. Esta sugestão obtive após a leitura da documentação* disponível no sandbox da MoIP, já que notei que a variável $errors nestas linhas não estava definida em lugar algum, portanto, a resposta para a MoIP era sempre "que houve erro".

* = https://desenvolvedor.moip.com.br/sandb ... nManual.do[/i]