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)
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)
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
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)
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 _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 _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 _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
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
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 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}
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())
def test_parse_decimal_string_with_float_input(input_val, expected_val): result = parse_decimal_string(input_val) assert result == expected_val
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 }
def round(self, value): return bankers_round(parse_decimal_string(value), self.decimals)