I want to begin with saying that I understand that this issue is certainly somewhat of an edge case. After all, who would want to order zero items of something? Well, my customers want. :) The short rationale for this is that some government customers does not want to order (some) their items immediately but unless they get a price on their invoice they will not (legally) be able to order the items later. A longer explanation can be given if you like.

So, to the issue… In uc_order/uc_order.module on line 1521 or thereabout the code inside uc_order_get_total() looks like this:

<?php
    foreach ($order->products as $product) {
      $price_info = array(
        'price' => $product->price,
        'qty' => ($product->qty) ? $product->qty : 1,
      );
      $context['subject'] = array(
        'order' => $order,
        'product' => $product,
        'node' => node_load($product->nid),
      );
      $total += uc_price($price_info, $context);
    }

?>

Especially the line:

<?php
        'qty' => ($product->qty) ? $product->qty : 1,
?>

prevents this use case. It would therefore be preferable that it change to something like:

<?php
        'qty' => ($product->qty >= 0) ? intval($product->qty) : 1,
?>

This works fine for a multitude of "numbers" I have thrown at it, like these:

<?php
2 >= 0 // true, qty becomes 2
"2" >= 0 // true, qty becomes 2
0 >= 0 // true, qty becomes 0
"0" >= 0 // true, qty becomes 0
-2 >= 0 // false, qty becomes 1
"-2" >= 0 // false, qty becomes 1
"foo" >= 0 // true, qty becomes 0
?>

I really hope something like this is doable.

Comments

NiklasBr’s picture

Title: uc_order uc_order_get_total() function can't handle zero quantity items » uc_order_get_total() function can't handle zero quantity items
TR’s picture

Category: Bug report » Feature request

See #1366576: Allow products with zero quantity in orders

I don't think there's a good use-case for allowing line items with zero quantity, and even if you make a good case, 6.x is the LAST place it's going to be changed. (Why are you developing a new site on D6 at this point in time, when D6 is just months away from being obsolete and unsupported?)

It sounds like you want the capability to generate a pro forma invoice. If that's the case, then zero quantity line items is not the way to go about it. Search for how to create a quoting system with Ubercart. Even quotes require a quantity, because prices in general depend on quantity.

NiklasBr’s picture

This is a procurement requirement that is in EU law, in the end it is your call whether or not that is an acceptable use case or not. But I certainly hope you understand where I am coming from when I ask for this.

This is not a new site, the first time this was discovered was about six months ago but more pressing matters left this issue further back in the issue queue. This is a legal requirement on how government entities in EU must go about when buying from external entities, so yes it is more or less a pro forma invoice. We don't care very much about zero quantity line items for now, but to be able to conform to the law we must be able to show zero quantity products.

In the end what matters is that the product should show quantity: zero and then the price of the product should not be included in the order total. Übercart today already supports the ability to have a zero-quantity product. It saves qty = 0 in the {uc_order_products} table already, however it still adds 1 x product's price to the order total.

This disconnect between the fact that Übercart actually allows saving zero-quantity items in orders and that uc_order_get_total() does not allow zero-quantity items leads me to believe that this is a bug.

NiklasBr’s picture

If we prepare a patch, will that be enough to accept this request? If not, what arguments will you accept as good enough to prove the utility of such a patch?

TR’s picture

Zero quantity line items in orders and in carts would require more than just a one or two line patch. Simpletests would have to be added to ensure that uc_roles doesn't grant roles if someone orders "0" items. Likewise for uc_file. Stock would need tests to ensure it operates correctly for zero quantity. You would have to come up with a new scheme for removing items from the cart when the user changes cart quantity from 1 to 0 - how can you distinguish between the case where the user wants to remove the item and user simply wants 0 items? We would also need tests and possibly code modification for Cart Links. Shipping and Payments are a problem too, because payment processors will not process zero quantity orders or items (if the order is submitted by item). Shipping would have to handle zero quantity when computing shipping costs - flat rate per item would have to exclude zero quantity items, for instance. Even though you may not personally use or want to use any of these things, if you change Ubercart to support zero quantity then ALL of Ubercart must be changed to support it.

Patches need to be made to the current branch first then backported if there is community interest. This is Drupal policy, because of the very real problem with maintaining module going forward. If this is only fixed in 6.x-2.x, then it's highly likely that the feature will never be put into the current version and that work won't be carried into the future codebase.

However, I still don't buy the use case - it seems you're trying to use the existing order object as a substitute for what you really want. Requiring a 0 quantity line item to show up in a previous order before that line item can be purchased doesn't make sense on a lot of levels. First because it means you can never buy anything from someone you haven't already purchased something from, and that's anti-competetive. Second, absence of quantity renders the price meaningless. A price for 0 quantity or 1 quantity is NOT the same as a price for 100 or 1000 quantity. A valid quote requires all the elements - quantity, price, delivery, shipping. A zero quantity item would only serve to indicate that an existing vendor is willing to sell you that item, but that is most certainly NOT sufficient to serve as a legally binding offer or bid. Even more, government procurement laws always have different rules for the size of the purchase; for example "small" purchases may be made by credit card by those with limited procurement authority, "medium" purchases may be made by purchase order by those with higher spending authority, while "large" purchase *must* be competitively bid. And perhaps some stages in between. Regardless, you must know the quantity to know which procurement regulations apply. And you must know the quantity for a valid bid, because without price you don't know the total.

So I don't understand entirely what you're trying to do with this, and your link does not point to a specific section or document that I can read to determine if you're interpreting the regulations correctly - I'm certainly not going to read ALL the EU procurement laws. My inclination is that zero quantity items don't belong in the order, and that providing the information you require is something that should be done a different way.

NiklasBr’s picture

If I understand you correctly… Then this indicates that there is a bug in uc_order.module because it saves zero-quantity items, no? Our assumption has always been that because uc_order_save() and uc_cart_add_item() allows us to set quantity of items to zero (i.e. the behavior we want and expect) that also it would be possible to have uc_order_get_total() do the same.

Patches need to be made to the current branch first then backported if there is community interest. This is Drupal policy…

This is only a Drupal core policy AFAIK. But I can certainly understand if you use the same policy for Übercart (do you have a patch/backport policy I can read?).

… but that is most certainly NOT sufficient to serve as a legally binding offer or bid.

Do you have any source for that, our controller would like to know.

First because it means you can never buy anything from someone you haven't already purchased something from, and that's anti-competetive. […] but that is most certainly NOT sufficient to serve as a legally binding offer or bid. Even more, government procurement laws always have different rules for the size of the purchase; for example "small" purchases may be made by credit card by those with limited procurement authority, "medium" purchases may be made by purchase order by those with higher spending authority, while "large" purchase *must* be competitively bid.

No. It just means that once a procurement has happened the parties do not need to enter into a year-long new negotiation for any additional procurements. I am not sure where you get your premise and conclusion from, both are false, if you strongly believe that you are correct I would like for you to contact our controller or send me your source. It would be very appreciated!

NiklasBr’s picture

Category: Feature request » Bug report
Status: Active » Closed (won't fix)

We understand why you are reluctant to not fix this (even if we do not agree on the rationale), therefore I am closing this issue so that we both may spend our time and energy where it better belong. The decision has been made to keep a modified version of uc_order.module despite the extra manual work required to keep it up to date.