def _process_line_quantity_and_price(self, source, sline, sl_kwargs):
        quantity_val = sline.pop("quantity", None)
        try:
            sl_kwargs["quantity"] = parse_decimal_string(quantity_val)
        except Exception as exc:
            msg = _("The quantity '%(quantity)s' (for line %(text)s) is invalid (%(error)s)") % {
                "text": sl_kwargs["text"],
                "quantity": quantity_val,
                "error": exc,
            }
            self.add_error(ValidationError(msg, code="invalid_quantity"))
            return False

        price_val = sline.pop("unitPrice", None)
        try:
            sl_kwargs["base_unit_price"] = source.create_price(parse_decimal_string(price_val))
        except Exception as exc:
            msg = _("The price '%(price)s' (for line %(text)s) is invalid (%(error)s)") % {
                "text": sl_kwargs["text"],
                "price": price_val,
                "error": exc
            }
            self.add_error(ValidationError(msg, code="invalid_price"))
            return False
        return True
    def _import_product(self, sku, data):
        product = create_from_datum(Product,
                                    sku,
                                    data,
                                    self.i18n_props,
                                    identifier_field="sku")
        if not product:
            return
        assert isinstance(product, Product)
        product.type = self.product_type
        product.tax_class = self.tax_class
        product.sales_unit = self.sales_unit
        product.full_clean()
        product.save()
        try:
            shop_product = product.get_shop_instance(self.shop)
        except ShopProduct.DoesNotExist:
            price = parse_decimal_string(data.get("price", "9.99"))
            shop_product = ShopProduct.objects.create(
                product=product, shop=self.shop, default_price_value=price)

        shop_product.suppliers.add(self.supplier)
        for limiter_name in ("limit_shipping_methods",
                             "limit_payment_methods"):
            limiter_val = data.get(limiter_name, ())
            m2m_field = getattr(shop_product,
                                limiter_name.replace("limit_", ""))
            if limiter_val:
                print("%s: Set %s to %s" %
                      (product.sku, limiter_name, limiter_val))
                setattr(shop_product, limiter_name, True)

                for identifier in limiter_val:
                    m2m_field.add(
                        m2m_field.model.objects.get(identifier=identifier))
            else:
                setattr(shop_product, limiter_name, False)
                m2m_field.clear()

        image_name = data.get("image")

        if image_name:
            self._attach_image_from_name(product, image_name, shop_product)

        category_identifier = data.get("category_identifier")

        if category_identifier:
            self._attach_category(product, shop_product, category_identifier)

        if data.get("discount_price"):
            discount_price = parse_decimal_string(
                data.get("discount_price", "9.99"))
            DiscountedProductPrice.objects.create(product=product,
                                                  shop=self.shop,
                                                  price_value=discount_price)

        shop_product.save()
        product.save()
        print("Product updated: %s" % product.sku)
Exemple #3
0
    def _process_line_quantity_and_price(self, source, sline, sl_kwargs):
        quantity_val = sline.pop("quantity", None)
        try:
            sl_kwargs["quantity"] = parse_decimal_string(quantity_val)
        except Exception as exc:
            msg = _(
                "The quantity '%(quantity)s' (for line %(text)s) is invalid (%(error)s)"
            ) % {
                "text": sl_kwargs["text"],
                "quantity": quantity_val,
                "error": exc,
            }
            self.add_error(ValidationError(msg, code="invalid_quantity"))
            return False

        is_product = bool(sline.get("type") == "product")
        price_val = sline.pop("baseUnitPrice",
                              None) if is_product else sline.pop(
                                  "unitPrice", None)
        try:
            sl_kwargs["base_unit_price"] = source.create_price(
                parse_decimal_string(price_val))
        except Exception as exc:
            msg = _(
                "The price '%(price)s' (for line %(text)s) is invalid (%(error)s)"
            ) % {
                "text": sl_kwargs["text"],
                "price": price_val,
                "error": exc
            }
            self.add_error(ValidationError(msg, code="invalid_price"))
            return False

        discount_val = sline.pop("discountAmount",
                                 parse_decimal_string(str("0.00")))
        try:
            sl_kwargs["discount_amount"] = source.create_price(
                parse_decimal_string(discount_val))
        except Exception as exc:
            msg = _(
                "The discount '%(discount)s' (for line %(text)s is invalid (%(error)s)"
            ) % {
                "discount": discount_val,
                "text": sl_kwargs["text"],
                "error": exc
            }
            self.add_error(ValidationError(msg, code="invalid_discount"))

        return True
    def _import_product(self, sku, data):
        product = create_from_datum(Product, sku, data, self.i18n_props, identifier_field="sku")
        if not product:
            return
        assert isinstance(product, Product)
        product.type = self.product_type
        product.tax_class = self.tax_class
        product.sales_unit = self.sales_unit
        product.full_clean()
        product.save()

        price = parse_decimal_string(data.get("price", "9.99"))
        shop_product, _ = ShopProduct.objects.update_or_create(
            product=product, shop=self.shop, defaults={"default_price_value": price}
        )
        shop_product.suppliers.add(self.supplier)
        for limiter_name in ("limit_shipping_methods", "limit_payment_methods"):
            limiter_val = data.get(limiter_name, ())
            m2m_field = getattr(shop_product, limiter_name.replace("limit_", ""))
            if limiter_val:
                print("%s: Set %s to %s" % (product.sku, limiter_name, limiter_val))
                setattr(shop_product, limiter_name, True)

                for identifier in limiter_val:
                    m2m_field.add(m2m_field.model.objects.get(identifier=identifier))
            else:
                setattr(shop_product, limiter_name, False)
                m2m_field.clear()

        image_name = data.get("image")

        if image_name:
            self._attach_image_from_name(product, image_name, shop_product)

        category_identifier = data.get("category_identifier")

        if category_identifier:
            self._attach_category(product, shop_product, category_identifier)

        if data.get("discount_price"):
            discount_price = parse_decimal_string(data.get("discount_price", "9.99"))
            DiscountedProductPrice.objects.update_or_create(
                product=product, shop=self.shop, defaults={"price_value": discount_price}
            )

        shop_product.save()
        product.save()
        print("Product updated: %s" % product.sku)
Exemple #5
0
    def update_quantity(self, line, value, **kwargs):
        new_quantity = int(parse_decimal_string(
            value))  # TODO: The quantity could be a non-integral value
        if new_quantity is None:
            return False

        if not (line and line["quantity"] != new_quantity):
            return False

        changed = False

        # Ensure sub-lines also get changed accordingly
        linked_lines = [line] + list(
            self.basket.find_lines_by_parent_line_id(line["line_id"]))
        for linked_line in linked_lines:
            errors = list(
                self._get_orderability_errors(linked_line, new_quantity))
            if errors:
                for error in errors:
                    error_texts = ", ".join(
                        six.text_type(sub_error) for sub_error in error)
                    message = u"%s: %s" % (linked_line.get("text")
                                           or linked_line.get("name"),
                                           error_texts)
                    messages.warning(self.request, message)
                continue
            self.basket.update_line(linked_line, quantity=new_quantity)
            linked_line["quantity"] = new_quantity
            changed = True

        return changed
Exemple #6
0
 def __init__(self, id, value, title, currency=None, **kwargs):
     self.currency = (currency or settings.SHOOP_HOME_CURRENCY)
     value = parse_decimal_string(value)
     value = format_currency(value,
                             currency=self.currency,
                             locale=get_current_babel_locale())
     super(DashboardMoneyBlock, self).__init__(id, value, title, **kwargs)
Exemple #7
0
 def __init__(self, id, value, title, currency, **kwargs):
     self.currency = currency
     value = parse_decimal_string(value)
     value = format_currency(value,
                             currency=self.currency,
                             locale=get_current_babel_locale())
     super(DashboardMoneyBlock, self).__init__(id, value, title, **kwargs)
Exemple #8
0
    def _initialize_product_line_data(self, product, supplier, shop, quantity=0):
        if product.variation_children.count():
            raise ValueError("Attempting to add variation parent to basket")

        return {
            # TODO: FIXME: Make sure line_id's are unique (not random)
            "line_id": str(random.randint(0, 0x7FFFFFFF)),
            "product": product,
            "supplier": supplier,
            "shop": shop,
            "quantity": parse_decimal_string(quantity),
        }
Exemple #9
0
    def _initialize_product_line_data(self, product, supplier, shop, quantity=0):
        if product.variation_children.count():
            raise ValueError("Attempting to add variation parent to basket")

        return {
            # TODO: FIXME: Make sure line_id's are unique (not random)
            "line_id": str(random.randint(0, 0x7FFFFFFF)),
            "product": product,
            "supplier": supplier,
            "shop": shop,
            "quantity": parse_decimal_string(quantity),
        }
Exemple #10
0
    def _process_line_quantity_and_price(self, source, sline, sl_kwargs):
        quantity_val = sline.pop("quantity", None)
        try:
            sl_kwargs["quantity"] = parse_decimal_string(quantity_val)
        except Exception as exc:
            msg = _("The quantity '%(quantity)s' (for line %(text)s) is invalid (%(error)s)") % {
                "text": sl_kwargs["text"],
                "quantity": quantity_val,
                "error": exc,
            }
            self.add_error(ValidationError(msg, code="invalid_quantity"))
            return False

        is_product = bool(sline.get("type") == "product")
        price_val = sline.pop("baseUnitPrice", None) if is_product else sline.pop("unitPrice", None)
        try:
            sl_kwargs["base_unit_price"] = source.create_price(parse_decimal_string(price_val))
        except Exception as exc:
            msg = _("The price '%(price)s' (for line %(text)s) is invalid (%(error)s)") % {
                "text": sl_kwargs["text"],
                "price": price_val,
                "error": exc
            }
            self.add_error(ValidationError(msg, code="invalid_price"))
            return False

        discount_val = sline.pop("discountAmount", parse_decimal_string(str("0.00")))
        try:
            sl_kwargs["discount_amount"] = source.create_price(parse_decimal_string(discount_val))
        except Exception as exc:
            msg = _("The discount '%(discount)s' (for line %(text)s is invalid (%(error)s)") % {
                "discount": discount_val,
                "text": sl_kwargs["text"],
                "error": exc
            }
            self.add_error(ValidationError(msg, code="invalid_discount"))

        return True
Exemple #11
0
    def _set_numeric_value(self, new_value):
        if isinstance(new_value, datetime.timedelta):
            value = new_value.total_seconds()
            if value == int(value):
                value = int(value)
        else:
            value = parse_decimal_string(new_value or 0)

        if self.attribute.type == AttributeType.INTEGER:
            value = int(value)

        if self.attribute.type == AttributeType.BOOLEAN:
            value = int(bool(value))

        self.numeric_value = value
        self.datetime_value = None
        self.untranslated_string_value = str(self.numeric_value)
        return
Exemple #12
0
    def _set_numeric_value(self, new_value):
        if isinstance(new_value, datetime.timedelta):
            value = new_value.total_seconds()
            if value == int(value):
                value = int(value)
        else:
            value = parse_decimal_string(new_value or 0)

        if self.attribute.type == AttributeType.INTEGER:
            value = int(value)

        if self.attribute.type == AttributeType.BOOLEAN:
            value = int(bool(value))

        self.numeric_value = value
        self.datetime_value = None
        self.untranslated_string_value = str(self.numeric_value)
        return
Exemple #13
0
    def update_quantity(self, line, value, **kwargs):
        new_quantity = int(parse_decimal_string(value))  # TODO: The quantity could be a non-integral value
        if new_quantity is None:
            return False

        if not (line and line["quantity"] != new_quantity):
            return False

        changed = False

        # Ensure sub-lines also get changed accordingly
        linked_lines = [line] + list(self.basket.find_lines_by_parent_line_id(line["line_id"]))
        for linked_line in linked_lines:
            errors = list(self._get_orderability_errors(linked_line, new_quantity))
            if errors:
                error_texts = ", ".join(six.text_type(error) for error in errors)
                message = u"%s: %s" % (linked_line.get("text") or linked_line.get("name"), error_texts)
                messages.warning(self.request, message)
                continue
            linked_line["quantity"] = new_quantity
            changed = True

        return changed
Exemple #14
0
 def __init__(self, id, value, title, **kwargs):
     value = parse_decimal_string(value)
     if int(value) == value:
         value = int(value)
     value = format_number(value, locale=get_current_babel_locale())
     super(DashboardNumberBlock, self).__init__(id, value, title, **kwargs)
Exemple #15
0
def handle_add(request,
               basket,
               product_id,
               quantity=1,
               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)
    shop_product = product.get_shop_instance(shop=request.shop)
    if not shop_product:
        raise ValidationError("Product not available in this shop",
                              code="product_not_available_in_shop")

    if supplier_id:
        supplier = shop_product.suppliers.filter(pk=supplier_id).first()
    else:
        supplier = shop_product.suppliers.first()

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

    try:
        quantity = parse_decimal_string(quantity)
        if not product.sales_unit.allow_fractions:
            if quantity % 1 != 0:
                msg = _("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"The quantity %s is not valid.") % quantity,
                              code="invalid_quantity")

    if quantity <= 0:
        raise ValidationError(_(u"The quantity %s is not valid.") % quantity,
                              code="invalid_quantity")

    shop_product.raise_if_not_orderable(supplier=supplier,
                                        quantity=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,
    }

    basket.add_product(**add_product_kwargs)

    return {'ok': basket.product_count, 'added': quantity}
Exemple #16
0
 def __init__(self, id, value, title, currency, **kwargs):
     self.currency = currency
     value = parse_decimal_string(value)
     value = format_currency(value, currency=self.currency, locale=get_current_babel_locale())
     super(DashboardMoneyBlock, self).__init__(id, value, title, **kwargs)
Exemple #17
0
def format_home_currency(value, locale=None):
    value = parse_decimal_string(value)
    return format_currency(value, currency=settings.SHOOP_HOME_CURRENCY, locale=locale or get_current_babel_locale())
Exemple #18
0
def test_parse_decimal_string_with_float_input(input_val, expected_val):
    result = parse_decimal_string(input_val)
    assert result == expected_val
Exemple #19
0
def handle_add(request, basket, product_id, quantity=1, 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)
    shop_product = product.get_shop_instance(shop=request.shop)
    if not shop_product:
        raise ValidationError("Product not available in this shop", code="product_not_available_in_shop")

    if supplier_id:
        supplier = shop_product.suppliers.filter(pk=supplier_id).first()
    else:
        supplier = shop_product.suppliers.first()

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

    try:
        quantity = parse_decimal_string(quantity)
        if not product.sales_unit.allow_fractions:
            if quantity % 1 != 0:
                msg = _(
                    "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"The quantity %s is not valid.") % quantity, code="invalid_quantity")

    if quantity <= 0:
        raise ValidationError(_(u"The quantity %s is not valid.") % 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
    )

    # 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,
    }

    basket.add_product(**add_product_kwargs)

    return {
        'ok': basket.product_count,
        'added': quantity
    }
Exemple #20
0
def test_parse_decimal_string_with_float_input(input_val, expected_val):
    result = parse_decimal_string(input_val)
    assert result == expected_val
Exemple #21
0
 def round(self, value):
     return bankers_round(parse_decimal_string(value), self.decimals)
Exemple #22
0
 def __init__(self, id, value, title, currency=None, **kwargs):
     self.currency = (currency or settings.SHOOP_HOME_CURRENCY)
     value = parse_decimal_string(value)
     value = format_currency(value, currency=self.currency, locale=get_current_babel_locale())
     super(DashboardMoneyBlock, self).__init__(id, value, title, **kwargs)
Exemple #23
0
 def __init__(self, id, value, title, **kwargs):
     value = parse_decimal_string(value)
     if int(value) == value:
         value = int(value)
     value = format_number(value, locale=get_current_babel_locale())
     super(DashboardNumberBlock, self).__init__(id, value, title, **kwargs)