Exemplo n.º 1
0
 def raise_if_not_orderable(self,
                            supplier,
                            customer,
                            quantity,
                            ignore_minimum=False):
     for message in self.get_orderability_errors(
             supplier=supplier,
             quantity=quantity,
             customer=customer,
             ignore_minimum=ignore_minimum):
         raise ProductNotOrderableProblem(message.args[0])
Exemplo n.º 2
0
def handle_add(  # noqa (C901)
        request,
        basket,
        product_id,
        quantity=1,
        unit_type='internal',
        supplier_id=None,
        **kwargs):
    """
    Handle adding a product to the basket.

    :param product_id: product ID to add (or if `child_product_id` is truey, the parent ID).
    :param quantity: quantity of products to add.
    :param child_product_id: child product ID to add (if truey).
    :param supplier_id: The supplier ID for the new line. If None, the first supplier is used.
    """
    product_id = int(product_id)

    product = get_object_or_404(Product, pk=product_id)

    if product.mode in (ProductMode.SIMPLE_VARIATION_PARENT,
                        ProductMode.VARIABLE_VARIATION_PARENT):
        raise ValidationError("Error! Invalid product.",
                              code="invalid_product")

    try:
        shop_product = product.get_shop_instance(shop=request.shop)
    except ShopProduct.DoesNotExist:
        raise ValidationError("Error! Product is not available in this shop.",
                              code="product_not_available_in_shop")

    if supplier_id:
        supplier = shop_product.suppliers.enabled(
            shop=shop_product.shop).filter(pk=supplier_id).first()
    else:
        supplier = shop_product.get_supplier(basket.customer, quantity,
                                             basket.shipping_address)

    if not supplier:
        raise ValidationError("Error! Invalid supplier.",
                              code="invalid_supplier")

    try:
        quantity = parse_decimal_string(quantity)
        if unit_type == 'display':
            quantity = shop_product.unit.from_display(quantity)
        if not product.sales_unit.allow_fractions:
            if quantity % 1 != 0:
                msg = _("Error! The quantity `%f` is not allowed. "
                        "Please use an integer value.") % quantity
                raise ValidationError(msg, code="invalid_quantity")
            quantity = int(quantity)
    except (ValueError, decimal.InvalidOperation):
        raise ValidationError(_(u"Error! The quantity `%s` is not valid.") %
                              quantity,
                              code="invalid_quantity")

    if quantity <= 0:
        raise ValidationError(_(u"Error! The quantity `%s` is not valid, "
                                "should be bigger than zero.") % quantity,
                              code="invalid_quantity")

    product_ids_and_quantities = basket.get_product_ids_and_quantities()
    already_in_basket_qty = product_ids_and_quantities.get(product.id, 0)
    shop_product.raise_if_not_orderable(supplier=supplier,
                                        quantity=(already_in_basket_qty +
                                                  quantity),
                                        customer=basket.customer)

    # If the product is a package parent, also check child products
    if product.is_package_parent():
        for child_product, child_quantity in six.iteritems(
                product.get_package_child_to_quantity_map()):
            already_in_basket_qty = product_ids_and_quantities.get(
                child_product.id, 0)
            total_child_quantity = (quantity * child_quantity)
            try:
                sp = child_product.get_shop_instance(shop=request.shop)
            except ShopProduct.DoesNotExist:
                raise ProductNotOrderableProblem(
                    "Error! Product %s is not available in shop %s." %
                    (child_product, request.shop))

            sp.raise_if_not_orderable(supplier=supplier,
                                      quantity=(already_in_basket_qty +
                                                total_child_quantity),
                                      customer=basket.customer)

    # TODO: Hook/extension point
    # if product.form:
    #     return {
    #         "error": u"Form required",
    #         "return": reverse_GET("product-form", kwargs={"pk": product.pk}, GET={"n": quantity})
    #     }

    add_product_kwargs = {
        "product": product,
        "quantity": quantity,
        "supplier": supplier,
        "shop": request.shop,
        "force_new_line": kwargs.get("force_new_line", False),
        "extra": kwargs.get("extra"),
        "parent_line": kwargs.get("parent_line")
    }
    line = basket.add_product(**add_product_kwargs)

    return {
        'ok': basket.smart_product_count,
        'line_id': line.line_id,
        'added': quantity
    }