def get_stocks(self, product): stocks = [] supplier_qs = Supplier.objects.enabled().filter(shop_products__product=product).distinct() # filtered by supplier supplier_id = int(parse_decimal_string(self.context["request"].query_params.get("supplier", 0))) if supplier_id: supplier_qs = supplier_qs.filter(pk=supplier_id) for supplier in supplier_qs: stock_status = supplier.get_stock_status(product.id) stocks.append({ "id": supplier.id, "name": supplier.name, "type": supplier.type, "logical_count": stock_status.logical_count, "physical_count": stock_status.physical_count, "message": stock_status.message, "error": stock_status.error }) return { "product": product.id, "sku": product.sku, "stocks": stocks }
def _set_numeric_value(self, new_value): if self.attribute.type == AttributeType.BOOLEAN and new_value is None: """ E-Commerce uses `django.forms.fields.NullBooleanField` in admin. Which can read in the `None` value. Note: This is being handled separately due backwards compatibility. TODO (2.0): Boolean should not be a special case and handling `None` should be same for every "numeric" value. """ self.numeric_value = None self.datetime_value = None self.untranslated_string_value = "" return 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
def test_parse_decimal_string_with_dirty_input(): assert parse_decimal_string('1e12') == Decimal(112) assert parse_decimal_string('foo1bar 1x2') == Decimal(112) assert parse_decimal_string('4a bc2def 8g.h5') == Decimal('428.5') assert parse_decimal_string(float('inf')) == Decimal('inf') assert parse_decimal_string(float('-inf')) == Decimal('-inf') assert str(parse_decimal_string(float('nan'))) == str(Decimal('nan')) assert parse_decimal_string('') == Decimal(0) assert parse_decimal_string(' ') == Decimal(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), }
def update_display_quantity(self, line, value, **kwargs): if not line: return False new_display_quantity = parse_decimal_string(value) if new_display_quantity is None: return False basket_line = self.basket.get_basket_line(line['line_id']) if basket_line and basket_line.product: unit = basket_line.shop_product.unit new_quantity = unit.from_display(new_display_quantity) else: new_quantity = new_display_quantity return self._update_quantity(line, new_quantity)
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 __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)
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)
def test_parse_decimal_string_with_unaccepted_input(value): with pytest.raises(decimal.InvalidOperation): parse_decimal_string(value)
def test_parse_decimal_string_with_normal_input(): assert parse_decimal_string('42') == Decimal(42) assert parse_decimal_string('0') == Decimal(0) assert parse_decimal_string(3.5) == Decimal('3.5') assert parse_decimal_string(-5) == Decimal(-5) assert parse_decimal_string('-5') == Decimal(-5)
def test_parse_decimal_string_with_float_input(input_val, expected_val): result = parse_decimal_string(input_val) assert result == expected_val
def update_quantity(self, line, value, **kwargs): new_quantity = parse_decimal_string(value) if new_quantity is None: return False return self._update_quantity(line, new_quantity)
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("Invalid product", code="invalid_product") try: shop_product = product.get_shop_instance(shop=request.shop) except ShopProduct.DoesNotExist: raise ValidationError("Product not available in this shop", code="product_not_available_in_shop") if supplier_id: supplier = shop_product.suppliers.enabled().filter(pk=supplier_id).first() else: supplier = shop_product.get_supplier(basket.customer, quantity, basket.shipping_address) if not supplier: raise ValidationError("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 = _( "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 ) # 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("%s not available in %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 }
def round(self, value): return bankers_round(parse_decimal_string(value), self.decimals)