Page 1 of 1

How to save bulk products on admin product list page on Opencart?

Posted: Sat Nov 11, 2017 6:17 am
by gokaydemir86
Hi. I want to save selected products automaticly by clicking a save button. Actually, I wrote some codes to make calculations with product price and customer group's special prices. And I have to edit 2 times a product. First, I enter the price and a percentage value, then save. So, the controller file (product.php) makes the calculations for special prices. And the second save is for saving these prices to database. This second save is just click edit and then click save :( That's why I need a "save all selected products" button.

I added a button on opencart product listing page : \admin\view\template\catalog\product_list.tpl

Code: Select all

    <button type="button" data-toggle="tooltip" title="<?php echo 'SAVE SELECTED'; ?>" class="btn btn-primary" onclick="$('#form-product').attr('action', '<?php echo $save_selected; ?>').submit()"><i class="fa fa-save"></i></button> 
And make the changes below on the controller file : \admin\controller\catalog\product.php

I used this function:

Code: Select all

    public function save_selected() {
		$this->load->language('catalog/product');

		$this->document->setTitle($this->language->get('heading_title'));

		$this->load->model('catalog/product');

		if (isset($this->request->post['selected']) && $this->validateCopy()) {
			foreach ($this->request->post['selected'] as $product_id) {
		
				  $data = array();
				  $data = $this->model_catalog_product->getProduct($product_id);
				  $this->model_catalog_product->editProduct($product_id, $data);				
			}

			$this->session->data['success'] = $this->language->get('text_success');

			$url = '';

			if (isset($this->request->get['filter_name'])) {
				$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
			}

			if (isset($this->request->get['filter_model'])) {
				$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
			}

			if (isset($this->request->get['filter_price'])) {
				$url .= '&filter_price=' . $this->request->get['filter_price'];
			}

			if (isset($this->request->get['filter_quantity'])) {
				$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
			}

			if (isset($this->request->get['filter_status'])) {
				$url .= '&filter_status=' . $this->request->get['filter_status'];
			}

			if (isset($this->request->get['sort'])) {
				$url .= '&sort=' . $this->request->get['sort'];
			}

			if (isset($this->request->get['order'])) {
				$url .= '&order=' . $this->request->get['order'];
			}

			if (isset($this->request->get['page'])) {
				$url .= '&page=' . $this->request->get['page'];
			}

			$this->response->redirect($this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL'));
		}

		$this->getList();
	}
And after the code :

Code: Select all

  $data['copy'] = $this->url->link('catalog/product/copy', 'token=' . $this->session->data['token'] . $url, 'SSL');
I added :

Code: Select all

 $data['save_selected'] = $this->url->link('catalog/product/save_selected', 'token=' . $this->session->data['token'] . $url, 'SSL');
However, when I selected some products and clicked the save button, nothing is happen and the selected products are disappeared. But they are still on database (with old values of course).

Is there any way to do that? What is wrong with my codes? I would appreciate if anyone gives suggestion.

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sat Nov 11, 2017 7:56 am
by straightlight
The demonstrated code above is incomplete. In order to properly save values for two separated saved actions, a better solution would be rather to use the similarity of the button-commission-add that is already used from the admin/view/template/sale/order_info.tpl file:

Code: Select all

<button id="button-commission-add" data-loading-text="<?php echo $text_loading; ?>" data-toggle="tooltip" title="<?php echo $button_commission_add; ?>" class="btn btn-success btn-xs"><i class="fa fa-plus-circle"></i></button>
Change the ID name into another one of your choice (with dashes if more than one word). Then, the use of ajax as the following example for delegating your function (also by changing the ID name of button-commission-add into the same ID one you chosed):

Code: Select all

$(document).delegate('#button-commission-add', 'click', function() {
	$.ajax({
		url: 'index.php?route=catalog/product/save_selected&token=<?php echo $token; ?>',
		type: 'post',
		dataType: 'json',
		beforeSend: function() {
			$('#button-commission-add').button('loading');
		},
		complete: function() {
			$('#button-commission-add').button('reset');
		},
		success: function(json) {
			$('.alert-dismissible').remove();

			if (json['error']) {
				$('#content > .container-fluid').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa fa-exclamation-circle"></i> ' + json['error'] + '</div>');
			}

			if (json['success']) {
                $('#content > .container-fluid').prepend('<div class="alert alert-success alert-dismissible"><i class="fa fa-check-circle"></i> ' + json['success'] + '</div>');
                	}
		},
		error: function(xhr, ajaxOptions, thrownError) {
			alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
		}
	});
});
Although, in your controller, the save_selected method would need to be handled with JSON.

After:

Code: Select all

public function save_selected() {
add:

Code: Select all

$json = array();
Then, before the ended closed bracket at the end of the method, add above:

Code: Select all

$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
From there, based on the incomplete code you provided, you can complete your statement with:

Code: Select all

// When there's an error message.
$json['error'] = 'My JSON error message'; // Replace this with your actual error message.

// When there's a success message.
$json['success'] = 'My JSON success message'; // Replace this with your actual error message.
in your save_selected() method.

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sat Nov 11, 2017 8:51 pm
by gokaydemir86
Hi straightlight. Thank you very much for your detailed answer. I'll try it a.s.a.p.

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sun Nov 12, 2017 9:17 am
by gokaydemir86
straightlight wrote:
Sat Nov 11, 2017 7:56 am
The demonstrated code above is incomplete. In order to properly save values for two separated saved actions, a better solution would be rather to use the similarity of the button-commission-add that is already used from the admin/view/template/sale/order_info.tpl file:

Code: Select all

<button id="button-commission-add" data-loading-text="<?php echo $text_loading; ?>" data-toggle="tooltip" title="<?php echo $button_commission_add; ?>" class="btn btn-success btn-xs"><i class="fa fa-plus-circle"></i></button>
Change the ID name into another one of your choice (with dashes if more than one word). Then, the use of ajax as the following example for delegating your function (also by changing the ID name of button-commission-add into the same ID one you chosed):

Code: Select all

$(document).delegate('#button-commission-add', 'click', function() {
	$.ajax({
		url: 'index.php?route=catalog/product/save_selected&token=<?php echo $token; ?>&product_id=' + this.value,
		type: 'post',
		dataType: 'json',
		beforeSend: function() {
			$('#button-commission-add').button('loading');
		},
		complete: function() {
			$('#button-commission-add').button('reset');
		},
		success: function(json) {
			$('.alert-dismissible').remove();

			if (json['error']) {
				$('#content > .container-fluid').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa fa-exclamation-circle"></i> ' + json['error'] + '</div>');
			}

			if (json['success']) {
                $('#content > .container-fluid').prepend('<div class="alert alert-success alert-dismissible"><i class="fa fa-check-circle"></i> ' + json['success'] + '</div>');
                	}
		},
		error: function(xhr, ajaxOptions, thrownError) {
			alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
		}
	});
});
Although, in your controller, the save_selected method would need to be handled with JSON.

After:

Code: Select all

public function save_selected() {
add:

Code: Select all

$json = array();
Then, before the ended closed bracket at the end of the method, add above:

Code: Select all

$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
From there, based on the incomplete code you provided, you can complete your statement with:

Code: Select all

// When there's an error message.
$json['error'] = 'My JSON error message'; // Replace this with your actual error message.

// When there's a success message.
$json['success'] = 'My JSON success message'; // Replace this with your actual error message.
in your save_selected() method.

Hi, I made the changes now. But it doesn't work :( Here is my save_selected function in controller file :

Code: Select all

 public function save_selected() {
		
		$json = array();
		
		$this->load->language('catalog/product');

		$this->document->setTitle($this->language->get('heading_title'));

		$this->load->model('catalog/product');		

$counter = 0;

		 if (isset($this->request->post['selected'])) {
			
			foreach ($this->request->post['selected'] as $product_id) {
				  $counter = $counter + 1;
				  $data = array();
				  $data = $this->model_catalog_product->getProduct($product_id);
				  $this->model_catalog_product->editProduct($product_id, $data);				  
			}
			
			$json['success'] = $counter . ' products are saved successfully. ';
			
			$url = '';

			if (isset($this->request->get['filter_name'])) {
				$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
			}

			if (isset($this->request->get['filter_model'])) {
				$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
			}

			if (isset($this->request->get['filter_price'])) {
				$url .= '&filter_price=' . $this->request->get['filter_price'];
			}

			if (isset($this->request->get['filter_quantity'])) {
				$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
			}

			if (isset($this->request->get['filter_status'])) {
				$url .= '&filter_status=' . $this->request->get['filter_status'];
			}

			if (isset($this->request->get['sort'])) {
				$url .= '&sort=' . $this->request->get['sort'];
			}

			if (isset($this->request->get['order'])) {
				$url .= '&order=' . $this->request->get['order'];
			}

			if (isset($this->request->get['page'])) {
				$url .= '&page=' . $this->request->get['page'];
			}

			$this->response->redirect($this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL'));
		} 

		$this->getList();
		

		$json['error'] =  $counter  . ' products are not saved!';
		
		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
		
	} 
When I click the Save Button, then it is written the json['error'] message : "0 products are saved!"
In my opinion, this function doesn't enter into the first if condition:

Code: Select all

 if (isset($this->request->post['selected'])) 
In order to be sure that, I comment all of lines including "json" codes (both on controller and .tpl file). And I left only the counter inside the foreach loop. Then it is working and counting correctly :) So I need more help. Could you look at my codes, please? Thank you for your help..

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sun Nov 12, 2017 9:43 am
by straightlight
Is your selected key included in your TPL file before launching Ajax? Also, is the selected key and value in the data post of Ajax?

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sun Nov 12, 2017 9:56 am
by gokaydemir86
straightlight wrote:
Sun Nov 12, 2017 9:43 am
Is your selected key included in your TPL file before launching Ajax? Also, is the selected key and value in the data post of Ajax?
I couldn't understand what you mean by "selected key" . Unfortunately, I don't know Ajax. I paste your codes to the end of my product_list.tpl file where starts <script type="text/javascript"><!--
And here are the codes that you gave:

Code: Select all

 $(document).delegate('#button-commission-add', 'click', function() {
	$.ajax({
		url: 'index.php?route=catalog/product/save_selected&token=<?php echo $token; ?>&product_id=' + this.value,
		type: 'post',
		dataType: 'json',
		beforeSend: function() {
			$('#button-commission-add').button('loading');
		},
		complete: function() {
			$('#button-commission-add').button('reset');
		},
		success: function(json) {
			$('.alert-dismissible').remove();

			if (json['error']) {
				$('#content > .container-fluid').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa fa-exclamation-circle"></i> ' + json['error'] + '</div>');
			}

			if (json['success']) {
                $('#content > .container-fluid').prepend('<div class="alert alert-success alert-dismissible"><i class="fa fa-check-circle"></i> ' + json['success'] + '</div>');
                	}
		},
		error: function(xhr, ajaxOptions, thrownError) {
			alert(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
		}
	});
}); 
And I added the button with ID = "button-commission-add" to .tpl file:
Before this line:

Code: Select all

  <button type="button" data-toggle="tooltip" title="<?php echo $button_copy; ?>" class="btn btn-default" onclick="$('#form-product').attr('action', '<?php echo $copy; ?>').submit()"><i class="fa fa-copy"></i></button>  
I added:

Code: Select all

 <button id="button-commission-add" data-loading-text="<?php echo 'saving products...'; ?>" data-toggle="tooltip" title="<?php echo 'SAVE SELECTED'; ?>" class="btn btn-success btn-xs"><i class="fa fa-plus-circle"></i></button> 

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sun Nov 12, 2017 10:14 am
by straightlight
In your ajax code, right above:

Code: Select all

$.ajax({
add:

Code: Select all

var selectedValues = $("input[name='selected[]']").map(function() {
			return $(this).val();
		}).get();
Then, find:

Code: Select all

dataType: 'json',
add right below:

Code: Select all

data: { selected : encodeURIComponent(selectedValues) },
Then, in your PHP file, you need to replace:

Code: Select all

if (isset($this->request->post['selected'])) {
with - let's say:

Code: Select all

if (!empty($selected)) {
Then, right above the replaced line, add:

Code: Select all

if (!empty($this->request->post['selected'])) {
    $selected = explode(',', trim($this->request->post['selected']));
}
This should resolve the objective.

Re: How to save bulk products on admin product list page on Opencart?

Posted: Sun Nov 12, 2017 12:54 pm
by straightlight
For quick saving the entire product values, however, followed is a free extension: https://www.opencart.com/index.php?rout ... n_id=26386