I read in the plan for commerce kickstart 2 that you concidered stock levels but ran out of time.

The module http://drupal.org/project/commerce_stock seems to work ok.

It would be nice to be able to edit the stock quantities like the price is admin/commerce/products under the quick edit link.

How could I make the stock levels editable inline?

Thanks for any help

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anonymous’s picture

would love to know too!

Maestro232’s picture

Upvote, but extend this further to the "Disable Stock For this Product" option.

jsacksick’s picture

Project: Commerce Kickstart » Commerce Backoffice
Version: 7.x-2.x-dev » 7.x-1.x-dev
Status: Active » Fixed

The quick edit form is provided by the Commerce Backoffice module.
There's no UI no manage that.
Here's the code that manage that part :

/**
 * Form callback: Returns the form for modifying the product price and status.
 */
function commerce_backoffice_product_quick_edit_form($form, &$form_state, $product) {
  $form_state['product'] = $product;

  $price_array = $product->commerce_price[LANGUAGE_NONE][0];
  $price = commerce_currency_amount_to_decimal($price_array['amount'], $price_array['currency_code']);

  $wrapper = drupal_html_id('commerce-backoffice-product-quick-edit-form');
  $form['#prefix'] = '<div class="container-inline" id="' . $wrapper . '">';
  $form['#suffix'] = '</div>';

  $form['price'] = array(
    '#type' => 'textfield',
    '#title' => t('Price'),
    '#title_display' => 'invisible',
    '#default_value' => sprintf("%.2f", $price),
    '#size' => 5,
  );
  $form['status'] = array(
    '#type' => 'select',
    '#title' => t('Status'),
    '#title_display' => 'invisible',
    '#options' => array(0 => t('Disabled'), 1 => t('Active')),
    '#default_value' => $product->status,
  );
  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#ajax' => array(
      'callback' => 'commerce_backoffice_product_quick_edit_form_ajax',
      'wrapper' => $wrapper,
    ),
  );
  if (!empty($form_state['product_saved'])) {
    $form['save']['#suffix'] = t('Saved');
  }

  return $form;
}

/**
 * Ajax callback for commerce_backoffice_product_quick_edit_form.
 */
function commerce_backoffice_product_quick_edit_form_ajax($form, &$form_state) {
  return $form;
}

/**
 * Submit callback for commerce_backoffice_product_quick_edit_form.
 */
function commerce_backoffice_product_quick_edit_form_submit($form, &$form_state) {
  $product = $form_state['product'];
  $currency_code = $product->commerce_price[LANGUAGE_NONE][0]['currency_code'];
  $product->commerce_price[LANGUAGE_NONE][0]['amount'] = commerce_currency_decimal_to_amount($form_state['values']['price'], $currency_code);
  $product->status = $form_state['values']['status'];
  commerce_product_save($product);

  $form_state['rebuild'] = TRUE;
  $form_state['product_saved'] = TRUE;
}

If you want to alter that, you could alter the form add the fields you want and replace our submit callback.

Maestro232’s picture

Fair enough.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

coyoterj’s picture

Status: Closed (fixed) » Active
FileSize
2.61 KB

Hi,

I'm trying to make a patch, but when i saved the value of stock and reload the page, only the first digit was saved. Eg. enter 423 => saved 4

My code snippet:

function commerce_backoffice_product_quick_edit_form($form, &$form_state, $product) {
(...)
  $stock = $product->commerce_stock['und'][0];
(...)
  $form['stock'] = array(
      '#type' => 'textfield',
      '#title' => t('Stock'),
      '#title_display' => 'invisible',
      '#default_value' => $stock,
      '#attributes' => array('title' => 'Estoque'),
      '#size' => 5,
   );
(...)
function commerce_backoffice_product_quick_edit_form_submit($form, &$form_state) {
(...)
  $product->commerce_stock['und'][0] = $form_state['values']['stock'];
(...)

At this moment, I don't run verification modules, etc.

Why only the one first digit is saved ?

Thanks!

coyoterj’s picture

Solved by correcting:

$stock = $product->commerce_stock['und'][0];

To:

$stock = $product->commerce_stock['und'][0]['value'];

Now, the value of the stock can changed here.

This is my first contribution to code, so my apologies to any failure. ;)

rbosscher’s picture

Thanks coyoterj for the inspiration but I think its better to use a alter function like jsacksick suggested.

This function you can use in a custom helper module


/**
 * alter function for commerce_backoffice_product_quick_edit_form.
 */
function YOURMODULE_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){   
  $product = $form_state['product'] ;
  $form['commerce_stock'] = array(
    '#type' => 'textfield',
    '#title' => t('Stock'),
    '#default_value' => $product->commerce_stock['und'][0]['value'],
    '#size' => 5,
  );
$form['#submit'][] = 'YOURMODULE_commerce_backoffice_product_quick_edit_form_submit';
}

/**
 * Submit callback for commerce_backoffice_product_quick_edit_form.
 */
function YOURMODULE_commerce_backoffice_product_quick_edit_form_submit($form, &$form_state) {
  $product = $form_state['product'];
  $currency_code = $product->commerce_price[LANGUAGE_NONE][0]['currency_code'];
  $product->commerce_price[LANGUAGE_NONE][0]['amount'] = commerce_currency_decimal_to_amount($form_state['values']['price'], $currency_code);
  $product->status = $form_state['values']['status'];
  $product->commerce_stock[LANGUAGE_NONE][0]['value'] = $form_state['values']['commerce_stock'];
  commerce_product_save($product);

  $form_state['rebuild'] = TRUE;
  $form_state['product_saved'] = TRUE;
}
coyoterj’s picture

Hi rbosscher,

I knew it had to do, but did not know how. :)
Well... I put the code in my module, but not worked. The field "stock" does not appear in the form :(
Yes, I cleaned all caches. :)
Then, I will study your solution and post here if I find something.

Thanks!

rbosscher’s picture

Probably obvious, but just to be sure:

Make sure you replace YOURMODULE with your module name (its in there 3 times)
Make also sure your stock field has the machine name commerce_stock (Not sure this could be anything else but will not hurt to check)
Safe, clear caches, fingers crossed... :)

coyoterj’s picture

Yes, I replaced the name YOURMODULE.
Yes, the fields's name is the same. You can check in previous posts.
Does the problem is not here ?

$form['#submit'][] = 'YOURMODULE_commerce_backoffice_product_quick_edit_form_submit';

I say this because of ajax call:
'callback' => 'commerce_backoffice_product_quick_edit_form_ajax',

/**
* Ajax callback for commerce_backoffice_product_quick_edit_form.
*/
function commerce_backoffice_product_quick_edit_form_ajax($form, &$form_state) {
  return $form;
}
rbosscher’s picture

$form['#submit'][] = 'YOURMODULE_commerce_backoffice_product_quick_edit_form_submit';

Overwrites the default submit handler (commerce_backoffice_product_quick_edit_form_submit) with the new attached submit handler

function YOURMODULE_commerce_backoffice_product_quick_edit_form_submit($form, &$form_state) { .. } 

I Think I know what the problem is:

replace

function YOURMODULE_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){   

whit:


function YOURMODULE_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$form_id){   

coyoterj’s picture

Hi rbosscher
Forgot a small detail ??
Or it was just a test with me ? :)

The problem is here:

function YOURMODULE_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){ 

Replace with:
1.
function YOURMODULE_form_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){

And

2.
$form['commerce_stock'] = array with $form['stock'] = array

3.
$product->commerce_stock[LANGUAGE_NONE][0]['value'] = $form_state['values']['commerce_stock']; with $product->commerce_stock[LANGUAGE_NONE][0]['value'] = $form_state['values']['stock'];

Yes! Now it works! :D

Thanks a lot, today I will update the module without fear :D

coyoterj’s picture

I put the full patch here:

https://gist.github.com/coyoterj/6247377

candelas’s picture

i am going to try this code, but i need it for two different forms, one for one worker that only can change stock and other for the director that can change price. for what i understand, this formula will affect both forms.. so should i use the same form and hide fields by permissions?
thanks for any tip ;)

candelas’s picture

thanks @rbosscher and @Icoyoterj for the documentation.
at the end i my client change his mind and workers will be able to change the price and i dont have to resolve that problem.

@Icoyoterj a minor correction, you should change in line 15 from

$form['#submit'][] = YOURMODULE_commerce_backoffice_product_quick_edit_form_submit';

to

$form['#submit'][] = 'YOURMODULE_commerce_backoffice_product_quick_edit_form_submit';

i used your code and i want that product state doesnt show in the quickedit form but i get a notice:

Notice: Undefined index: status in commerce_backoffice_product_quick_edit_form_submit() (line 375 of /home/ftp/xxx/profiles/commerce_kickstart/modules/contrib/commerce_backoffice/commerce_backoffice_product.module).

my module

  /**
* alter function for commerce_backoffice_product_quick_edit_form.
*/
  function MYMODULE_form_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){
  $product = $form_state['product'] ;
  $form['stock'] = array(
  '#type' => 'textfield',
  '#title' => t('Stock'),
  '#title_display' => 'before',
  '#default_value' => $product->commerce_stock['und'][0]['value'],
  '#size' => 5,
  );
  $form['price']['#title_display'] = 'before';
  unset($form['status']);
  $form['#submit'][] = 'MYMODULE_commerce_backoffice_product_quick_edit_form_submit';
}
/**
* Submit callback for commerce_backoffice_product_quick_edit_form.
*/
function MYMODULE_commerce_backoffice_product_quick_edit_form_submit($form, &$form_state) {
  $product = $form_state['product'];
  $currency_code = $product->commerce_price[LANGUAGE_NONE][0]['currency_code'];
  $product->commerce_price[LANGUAGE_NONE][0]['amount'] = commerce_currency_decimal_to_amount($form_state['values']['price'], $currency_code);

  //here i removed the status field
  //$product->status = $form_state['values']['status']; 
  $product->commerce_stock[LANGUAGE_NONE][0]['value'] = $form_state['values']['stock'];
  commerce_product_save($product);
  $form_state['rebuild'] = TRUE;
  $form_state['product_saved'] = TRUE;
}

i will appreciate if you give to me any tip, since i am learning to work with forms in drupal :)

rbosscher’s picture

if you add above the line
$form['stock'] = array(
the line:
unset($form['status']);
You should get rid of the notice and the field.

candelas’s picture

@rbosscher thanks for your fast answer, i did it but i keep getting the notice (i truncate the cache tables on the db).

the code

function MYMODULE_form_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){
  $product = $form_state['product'] ;
  unset($form['status']);
  $form['stock'] = array(
  '#type' => 'textfield',
  '#title' => t('Stock'),
  '#title_display' => 'before',
  '#default_value' => $product->commerce_stock['und'][0]['value'],
  '#size' => 5,
  );
  $form['price']['#title_display'] = 'before';  
  $form['#submit'][] = 'MYMODULE_commerce_backoffice_product_quick_edit_form_submit';
}
rbosscher’s picture

Can you tell me what the notice is and on which line it is and give the corresponding line?
Your previous posted notice is in the submit handler commerce_backoffice_product_quick_edit_form_submit
while your custom submit handler is: ocultar_vt_commerce_backoffice_product_quick_edit_form_submit

candelas’s picture

the notice always is
Notice: Undefined index: status in commerce_backoffice_product_quick_edit_form_submit() (line 375 of /home/ftp/xxx/profiles/commerce_kickstart/modules/contrib/commerce_backoffice/commerce_backoffice_product.module).

maybe i have to unset in the MYMODULE_commerce_backoffice_product_quick_edit_form_submit?

thanks

candelas’s picture

i found the solution. instead of

unset($form['status']);

in
function MYMODULE_form_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){

i used

$form['status']['#access'] = FALSE;

and the warnings went away :)
i hope someone can use it!
thanks @rbosscher

candelas’s picture

Status: Active » Closed (fixed)
zooter626’s picture

thanks @coyoterj for #14 and @candelas for the minor correction. code works great, and it's exactly what i needed!

andyg5000’s picture

Here's an updated example that doesn't use LANGUAGE NONE and includes validation

/**
 * Implements hook_form_FORM_ID_alter().
 */
function MYMODULE_form_commerce_backoffice_product_quick_edit_form_alter(&$form, &$form_state, &$product){
  $product = $form_state['product'];
  $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
  $form['stock'] = array(
    '#type' => 'textfield',
    '#title' => t('Stock'),
    '#title_display' => 'before',
    '#default_value' => !empty($product->commerce_stock) ? $product_wrapper->commerce_stock->value() : 0,
    '#size' => 5,
  );
  $form['price']['#title_display'] = 'before';
  $form['#validate'][] = 'MYMODULE_commerce_backoffice_product_quick_edit_form_validate';
  $form['#submit'][] = 'MYMODULE_commerce_backoffice_product_quick_edit_form_submit';
}

/**
 * Validation callback to make sure stock is numeric.
 */
function MYMODULE_commerce_backoffice_product_quick_edit_form_validate($form, &$form_state) {
  if (!empty($form_state['values']['stock'])) {
    if (!is_numeric($form_state['values']['stock'])) {
      form_set_error('stock', t('Please enter a numeric stock value'));
    }
  }
}

/**
 * Submit callback to update the product stock.
 */
function MYMODULE_commerce_backoffice_product_quick_edit_form_submit($form, $form_state) {
  $product = $form_state['product'];
  if (!empty($product) && !empty($form_state['values']['stock'])) {
    $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
    $product_wrapper->commerce_stock->set($form_state['values']['stock']);
    commerce_product_save($product);
  }
}
rbosscher’s picture

Thinking about this further.

We could do someting like:


//Load all fields form the product entity and attacht to form
field_attach_form('commerce_product', $product, $form, $form_state, NULL, array());

Delete fields that are unnecessary
unset($form['title_field']);
unset($form['field_images']);
unset($form['field_purchase_price']);

Actually we could easely create a ui for the module so you can select wich fields to use in the quick edit form

lanetterm’s picture

I took the andyg5000 's code from comment 24 and wrapped a module around it.
Works great, does just what I need - Thanks Andy
I uploaded it to github, thinking it might save someone else a few minutes.

https://github.com/lanette/commerce_stock_quick_edit

szymon.l’s picture

This functionality is great, but I have problem with the code from @andyg5000

After enabling module, and clicking "quick edit", I have an AJAX ERROR:

AJAX HTTP.
HTTP Error: 200
...
StatusText: OK
ResponseText: Warning: strstr() expects parameter 1 to be string, object given in strstr() (line 88 of /....../sites/all/modules/commerce_wishlist/commerce_wishlist.module).

this line is pointing to this function:

<?php
/**
 * Implements hook_form_alter().
 */
function commerce_wishlist_form_alter(&$form, &$form_state, $form_id) {
  if (strstr($form_id, 'commerce_cart_add_to_cart_form')) {
    if (isset($form_state['build_info']['args'][0]->data['context']['view'])) {
      if ($form_state['build_info']['args'][0]->data['context']['view']['view_name'] == 'wishlist') {
        return;
      }
    }

    $form += commerce_wishlist_add_form();
  }
}
?>

help would be appreciated..

georgemastro’s picture

Same problem here as #27

szymon.l’s picture

When I got rid of commerce wishlist module, my error changed to:

Wystąpił błąd w AJAX HTTP.
Error HTTP: 200

Path: .../commerce_backoffice/variations/141
StatusText: OK
ResponseText: Warning: strpos() expects parameter 1 to be string, object given in strpos() (line 295 of .../sites/all/modules/views_bulk_operations/views_bulk_operations.module).
shanejensen’s picture

I was having the same issue reported in #29. The problem appears to have been caused by Views Bulk Operations not being enabled because the version of PHP running was lower than 5.29 which is required by VBO. Once PHP was upgrade and VBO was operational the issue went away.

szymon.l’s picture

in my case, VBO is enabled and my php ver is 5.5.3 (one server) and 5.3.16 on the other...

Zekvyrin’s picture

Issue summary: View changes

thx andyg5000 & lanetterm for the code

Yes it did save me some time :)

Collins405’s picture

#26 works perfectly for me with latest commerce kickstart

RAWDESK’s picture

#26 works for me too! thanks for the contribution!
Within a few weeks i will investigate this wrap-up to have additional fields enabled, such as split currency prices added through the Multicurrency module :
https://www.drupal.org/project/commerce_multicurrency

Anonymous’s picture

This is a little old already, but I think I'm not the only one looking for a good solution for adding fields to the quick edit form.

#24 works fine, so thank you for that! Although at first I got an ajax error (500) when I clicked the quick edit -button, but it was solved by turning off the Drupal For Firebug -module. I don't know why that happened, but if someone has any kind of clue, feel free to clarify!

I think an UI for adding/removing fields would be a nice add.

spgd01’s picture

Category: Support request » Feature request
Status: Closed (fixed) » Active

SWEET #26 works great! thanks. Can we add a IU for adding removing fields to the quick edit Backoffice module? Or perhaps instructions on how to edit the proper view?
thanks.

drakythe’s picture

#26 does work great, with one minor exception: If you try to use the quickedit stuff outside of the provided backoffice megarow view, you get a fun error where $form_id has been converted from a string to an object. I submitted a pull request on Github to fix the issue.

DaleTrexel’s picture

Thank you lanetterm in #24 for the module version! It looks like drakythe's pull request has not been granted, but I can confirm that it is an important fix to apply, especially when using the quickedit form outside the Backoffice Product variations form.

However, I have another problem when using the module (patched) outside the Backoffice Product variations form: the form works fine the first time you use it, but if you go back and update a variant a second time without re-loading the view, the variant's values in the quickedit form gets applied to every other variant visible in the view! This is especially bad without an easy undo function.

The quickedit form seems to work fine when used in its original state (price & activity state editing only), both within the "Commerce Backoffice: Product variations (Commerce Product)" view and other views you might add the field to. (I created a view for all variants with the goal to more easily update stock and shipping details on a single page, without having to toggle forms into view.) However, once I used hook-form-alter to add fields to the form, the form started misbehaving. I tried initially with a custom module that does basically the same as what lanetterm's module does (but with shipping dimensions too), then I switched to lanetterm's module to see if the problem was general or specific to my own module. It seems to be something with the general approach.

Once the new fields and callbacks are added to the original quickedit form, something about the form changes such that each quickedit form in a list of variants works properly the first time, but if you submit a second time, the whole page reloads and the form's values are applied to each variant on the page. I presume some form property/value is not being properly re-set after the initial form submission, but so far I haven't been able to figure out what it is, or how one might fix it.

What seems weird is that the quickedit form continues to work properly on the Backoffice Product variations page; it's just the new view where the quickedit forms misbehave.