Пример #1
0
    def getVariants(self):
        """
        """
        result = []
        pvm = IProductVariantsManagement(self.context)

        for variant in pvm.getVariants():

            # Options
            properties = []
            properties_ids = {}
            for property in variant.getForProperties():
                property_id, option_id = property.split(":")
                properties_ids[property_id] = option_id
                titles = getTitlesByIds(variant, property_id, option_id)
                if titles is None:
                    continue
                properties.append(titles)

            result.append({
                "id"             : variant.getId(),
                "path"           : "/".join(variant.getPhysicalPath()),
                "article_id"     : variant.getArticleId(),
                "title"          : variant.Title(),
                "url"            : variant.absolute_url(),
                "properties"     : properties,
                "properties_ids" : properties_ids,
                "price"          : variant.getPrice(),
            })
        return result
Пример #2
0
    def addVariants(self):
        """
        """
        putils = getToolByName(self.context, "plone_utils")

        title = self.request.get("title", "")
        url = self.context.absolute_url() + "/manage-variants-view"

        if not title:
            putils.addPortalMessage("Please provide a variant title")
            return self.request.response.redirect(url)

        article_id = self.request.get("article_id", "")
        price = self.request.get("price", 0.0)

        try:
            price = float(price)
        except ValueError:
            price = 0.0

        properties = self._getPropertiesAsList()

        pvm = IProductVariantsManagement(self.context)
        result = pvm.addVariants(properties, title, article_id, price)

        if result == False:
            putils.addPortalMessage(MESSAGES["VARIANT_ALREADY_EXISTS"])
        else:
            putils.addPortalMessage(MESSAGES["VARIANT_ADDED"])

        self.request.response.redirect(url)
Пример #3
0
    def asDict(self):
        """
        """
        pvm = IProductVariantsManagement(self.context)
        
        if pvm.hasVariants() == True:
            variant = pvm.getSelectedVariant() or pvm.getDefaultVariant()
            return IData(variant).asDict()
        else:
            # price
            cm    = ICurrencyManagement(self.context)
            price = IPrices(self.context).getPriceForCustomer()
            price = cm.priceToString(price)

            # image
            image = IImageManagement(self.context).getMainImage()
            if image is not None:
                image = "%s/image_%s" % (image.absolute_url(), "preview")

            images = []
            for temp in IImageManagement(self.context).getImages():
                images.append("%s/image_tile" % temp.absolute_url())
            
            return {
                "article_id"  : self.context.getArticleId(),                
                "title"       : self.context.Title(),
                "short_title" : self.context.getShortTitle() or self.context.Title(),
                "description" : self.context.Description(),
                "url"         : self.context.absolute_url(),
                "price"       : price,
                "image"       : image,
                "images"      : images,
                "text"        : self.context.getText(),
                "short_text"  : self.context.getShortText(),
            }        
Пример #4
0
    def addVariants(self):
        """
        """
        putils = getToolByName(self.context, "plone_utils")

        title = self.request.get("title", "")
        url = self.context.absolute_url() + "/manage-variants-view"

        if not title:
            putils.addPortalMessage("Please provide a variant title")
            return self.request.response.redirect(url)

        article_id = self.request.get("article_id", "")
        price = self.request.get("price", 0.0)

        try:
            price = float(price)
        except ValueError:
            price = 0.0

        properties = self._getPropertiesAsList()

        pvm = IProductVariantsManagement(self.context)
        result = pvm.addVariants(properties, title, article_id, price)

        if result == False:
            putils.addPortalMessage(MESSAGES["VARIANT_ALREADY_EXISTS"])
        else:
            putils.addPortalMessage(MESSAGES["VARIANT_ADDED"])

        self.request.response.redirect(url)
Пример #5
0
    def getStockInformation(self):
        """
        """
        shop = self._getShop()
        sm = IStockManagement(shop)

        pvm = IProductVariantsManagement(self.context)

        if pvm.hasVariants() == False:
            stock_information = sm.getStockInformationFor(self.context)
        else:
            product_variant = pvm.getSelectedVariant()

            # First, we try to get information for the selected product variant
            stock_information = sm.getStockInformationFor(product_variant)

            # If nothing is found, we try to get information for parent product
            # variants object.
            if stock_information is None:
                stock_information = sm.getStockInformationFor(self.context)

        if stock_information is None:
            return None

        return IData(stock_information).asDict()
Пример #6
0
    def getVariants(self):
        """
        """
        result = []
        pvm = IProductVariantsManagement(self.context)

        for variant in pvm.getVariants():

            # Options
            properties = []
            properties_ids = {}
            for property in variant.getForProperties():
                property_id, option_id = property.split(":")
                properties_ids[property_id] = option_id
                titles = getTitlesByIds(variant, property_id, option_id)
                if titles is None:
                    continue
                properties.append(titles)

            result.append({
                "id": variant.getId(),
                "path": "/".join(variant.getPhysicalPath()),
                "article_id": variant.getArticleId(),
                "title": variant.Title(),
                "url": variant.absolute_url(),
                "properties": properties,
                "properties_ids": properties_ids,
                "price": variant.getPrice(),
            })
        return result
Пример #7
0
 def getProperties(self):
     """
     """
     pvm = IProductVariantsManagement(self.context)
     if pvm.hasVariants():
         return self._getPropertiesForVariants()
     else:
         return self._getPropertiesForConfiguration()
Пример #8
0
    def __init__(self, context):
        """
        """
        pvm = IProductVariantsManagement(context)
        shop = IShopManagement(context).getShop()

        self.context = context

        self.gross_prices = shop.getGrossPrices()
        self.has_variants = pvm.hasVariants()
        self.taxes = ITaxes(context)

        if self.has_variants:
            self.product_variant = \
                pvm.getSelectedVariant() or pvm.getDefaultVariant()
Пример #9
0
    def __init__(self, context):
        """
        """
        pvm  = IProductVariantsManagement(context)
        shop = IShopManagement(context).getShop()
        
        self.context = context

        self.gross_prices = shop.getGrossPrices()
        self.has_variants = pvm.hasVariants()
        self.taxes = ITaxes(context)

        if self.has_variants:
            self.product_variant = \
                pvm.getSelectedVariant() or pvm.getDefaultVariant()
Пример #10
0
def deleteProperty(property, event):
    """Removes property from all existing product variants.
    """
    product = property.aq_inner.aq_parent
    pvm = IProductVariantsManagement(product)
    
    if pvm.hasVariants() == False:
        return 
        
    to_delete_property_id = property.getId()
    for variant in pvm.getVariants():
        new_properties = []
        for variant_property in variant.getForProperties():
            variant_property_id = variant_property.split(":")[0]
            if variant_property_id != to_delete_property_id:
                new_properties.append(variant_property)
        new_properties.sort()

        variant.setForProperties(new_properties)
Пример #11
0
def deleteProperty(property, event):
    """Removes property from all existing product variants.
    """
    product = property.aq_inner.aq_parent
    pvm = IProductVariantsManagement(product)

    if pvm.hasVariants() == False:
        return

    to_delete_property_id = property.getId()
    for variant in pvm.getVariants():
        new_properties = []
        for variant_property in variant.getForProperties():
            variant_property_id = variant_property.split(":")[0]
            if variant_property_id != to_delete_property_id:
                new_properties.append(variant_property)
        new_properties.sort()

        variant.setForProperties(new_properties)
Пример #12
0
    def saveVariants(self):
        """Saves all variants.
        """
        article_ids = {}
        prices = {}
        properties = {}
        titles = {}

        for id, value in self.request.form.items():
            if id.startswith("price"):
                prices[id[6:]] = value
            elif id.startswith("article-id"):
                article_ids[id[11:]] = value
            elif id.startswith("title"):
                titles[id[6:]] = value
            elif id.startswith("property"):
                property_id, variant_id = id.split("|")
                property_id = property_id[9:]
                if properties.has_key(variant_id) == False:
                    properties[variant_id] = []
                properties[variant_id].append("%s:%s" % (property_id, value))

        pvm = IProductVariantsManagement(self.context)
        for variant in pvm.getVariants():
            # Title
            variant.setTitle(titles[variant.getId()])

            # Article ID
            variant.setArticleId(article_ids[variant.getId()])

            # Price
            variant.setPrice(prices[variant.getId()])

            properties[variant.getId()].sort()
            variant.setForProperties(properties[variant.getId()])
            variant.reindexObject()

        putils = getToolByName(self.context, "plone_utils")
        putils.addPortalMessage(MESSAGES["VARIANTS_SAVED"])

        url = self.context.absolute_url() + "/manage-variants-view"
        self.request.response.redirect(url)
Пример #13
0
    def saveVariants(self):
        """Saves all variants.
        """
        article_ids = {}
        prices = {}
        properties = {}
        titles = {}

        for id, value in self.request.form.items():
            if id.startswith("price"):
                prices[id[6:]] = value
            elif id.startswith("article-id"):
                article_ids[id[11:]] = value
            elif id.startswith("title"):
                titles[id[6:]] = value
            elif id.startswith("property"):
                property_id, variant_id = id.split("|")
                property_id = property_id[9:]
                if properties.has_key(variant_id) == False:
                    properties[variant_id] = []
                properties[variant_id].append("%s:%s" % (property_id, value))

        pvm = IProductVariantsManagement(self.context)
        for variant in pvm.getVariants():
            # Title
            variant.setTitle(titles[variant.getId()])

            # Article ID
            variant.setArticleId(article_ids[variant.getId()])

            # Price
            variant.setPrice(prices[variant.getId()])

            properties[variant.getId()].sort()
            variant.setForProperties(properties[variant.getId()])
            variant.reindexObject()

        putils = getToolByName(self.context, "plone_utils")
        putils.addPortalMessage(MESSAGES["VARIANTS_SAVED"])

        url = self.context.absolute_url() + "/manage-variants-view"
        self.request.response.redirect(url)
Пример #14
0
    def _information(self):
        """
        """
        shop = IShopManagement(self.context).getShop()
        im = IInformationManagement(shop)

        pvm = IProductVariantsManagement(self.context)

        if pvm.hasVariants() == False:
            information = im.getInformationPagesFor(self.context)
        else:
            product_variant = pvm.getSelectedVariant()

            # First, we try to get information for the selected product variant
            information = im.getInformationPagesFor(product_variant)

            # If nothing is found, we try to get information for parent product
            # variants object.
            if information is None:
                information = im.getInformationPagesFor(self.context)

        return information
Пример #15
0
    def _information(self):
        """
        """
        shop = IShopManagement(self.context).getShop()
        im = IInformationManagement(shop)
        
        pvm = IProductVariantsManagement(self.context)
        
        if pvm.hasVariants() == False:
            information = im.getInformationPagesFor(self.context)
        else:
            product_variant = pvm.getSelectedVariant()

            # First, we try to get information for the selected product variant
            information = im.getInformationPagesFor(product_variant)

            # If nothing is found, we try to get information for parent product 
            # variants object.
            if information is None:
                information = im.getInformationPagesFor(self.context)
            
        return information
Пример #16
0
    def __call__(self):
        """
        """
        # Set last seen products
        title = self.context.Title()
        short_title = title[:10] + "..."

        url = self.context.absolute_url()
            
        last_products = self.request.SESSION.get("last_products", [])
        if len(last_products) > 5:
            last_products = last_products[0:-1]

        urls = [p["url"] for p in last_products]

        if self.context.absolute_url() not in urls:
            last_products.insert(
                0, {
                    "title" : title,
                    "short_title" : short_title,
                    "url" : url
                    }
            )

        self.request.SESSION.set("last_products", last_products)

        pvm = IProductVariantsManagement(self.context)
        if pvm.hasVariants() == True and \
           self.request.get("variant_selected", None) is not None:

            selected_variant = pvm.getSelectedVariant()

            if selected_variant is None:
                putils = getToolByName(self.context, "plone_utils")
                putils.addPortalMessage(MESSAGES["VARIANT_DONT_EXIST"])

        return super(ProductView, self).__call__()
Пример #17
0
    def asDict(self):
        """
        """
        pvm = IProductVariantsManagement(self.context)

        if pvm.hasVariants() == True:
            variant = pvm.getSelectedVariant() or pvm.getDefaultVariant()
            return IData(variant).asDict()
        else:
            # price
            cm = ICurrencyManagement(self.context)
            price = IPrices(self.context).getPriceForCustomer()
            price = cm.priceToString(price)

            # image
            image = IImageManagement(self.context).getMainImage()
            if image is not None:
                image = "%s/image_%s" % (image.absolute_url(), "preview")

            images = []
            for temp in IImageManagement(self.context).getImages():
                images.append("%s/image_tile" % temp.absolute_url())

            return {
                "article_id": self.context.getArticleId(),
                "title": self.context.Title(),
                "short_title": self.context.getShortTitle()
                or self.context.Title(),
                "description": self.context.Description(),
                "url": self.context.absolute_url(),
                "price": price,
                "image": image,
                "images": images,
                "text": self.context.getText(),
                "short_text": self.context.getShortText(),
            }
Пример #18
0
    def getPriceForCustomer(self, formatted=True):
        """
        """
        p = IPrices(self.context)
        price = p.getPriceForCustomer()

        if IProductVariantsManagement(self.context).hasVariants() == False:
            total_diff = 0.0
            pm = IPropertyManagement(self.context)
            for property_id, selected_option in self.request.form.items():
                if property_id.startswith("property"):
                    total_diff += pm.getPriceForCustomer(
                        property_id[42:],
                        selected_option
                    )
            price += total_diff

        if formatted == True:
            cm = ICurrencyManagement(self.context)
            return cm.priceToString(price, suffix=None)
        else:
            return price
Пример #19
0
    def getStandardPriceForCustomer(self, formatted=True):
        """Returns the standard price for a customer when the product is for
        sale. Used to display the crossed-out standard price.
        """
        p = IPrices(self.context)
        price = p.getPriceForCustomer(effective=False)

        if IProductVariantsManagement(self.context).hasVariants() == False:
            total_diff = 0.0
            pm = IPropertyManagement(self.context)
            for property_id, selected_option in self.request.form.items():
                if property_id.startswith("property"):
                    total_diff += pm.getPriceForCustomer(
                        property_id[42:],
                        selected_option
                    )
            price + total_diff

        if formatted == True:
            cm = ICurrencyManagement(self.context)
            return cm.priceToString(price, suffix = None)
        else:
            return price
Пример #20
0
    def addToCart(self, redirect=True, add_accessories=True):
        """
        """
        shop = IShopManagement(self.context).getShop()
        cm = ICartManagement(shop)

        cart = cm.getCart()
        if cart is None:
            cart = cm.createCart()

        pvm = IProductVariantsManagement(self.context)
        if pvm.hasVariants():

            # Get the actual "product"
            product = pvm.getSelectedVariant() or pvm.getDefaultVariant()

            # Using here the selected product ensures that we save the right
            # properties. This is important when the selected variant doesn't
            # exist.
            properties = []
            for property in product.getForProperties():
                property_id, selected_option = property.split(":")
                properties.append({
                    "id": property_id,
                    "selected_option": selected_option,
                })
        else:

            # The product is the context
            product = self.context

            # Unlike above we take the properties out of the request, because
            # there is no object wich stores the different properties.
            properties = []
            for property in IPropertyManagement(product).getProperties():
                selected_option_id = self.request.get(
                    "property_%s_%s" % (product.UID(), property.getId()))

                # If nothing is selected we take the first option of the
                # property
                if (selected_option_id is None) or (selected_option_id
                                                    == "select"):
                    property = IPropertyManagement(product).getProperty(
                        property.getId())
                    property_options = property.getOptions()

                    if property_options:
                        selected_option = property.getOptions()[0]
                        selected_option_id = selected_option["id"]
                    else:
                        selected_option_id = ""

                properties.append({
                    "id": property.getId(),
                    "selected_option": selected_option_id
                })

        # get quantity
        quantity = int(
            self.context.request.get("%s_quantity" % self.context.UID(), 1))

        # returns true if the product was already within the cart
        result, item_id = IItemManagement(cart).addItem(
            product, tuple(properties), quantity)

        # Add product to session (for display on add to cart view)
        if self.request.SESSION.get("added-to-cart") is None:
            self.request.SESSION["added-to-cart"] = []
        self.request.SESSION["added-to-cart"].append(item_id)

        # Add the accessories
        if add_accessories == True:
            catalog = getToolByName(self.context, "portal_catalog")
            accessories = tuplize(self.request.get("accessories", []))
            for uid in accessories:
                try:
                    brain = catalog.searchResults(UID=uid)[0]
                except IndexError:
                    continue

                # We reuse the same view with an other context. The context are
                # the accessories
                product = brain.getObject()
                view = getMultiAdapter((product, self.request),
                                       name="addToCart")
                view.addToCart(redirect=False, add_accessories=False)

        if redirect == True:
            # Set portal message
            # putils = getToolByName(self.context, "plone_utils")
            # if result == True:
            #     putils.addPortalMessage(MESSAGES["CART_INCREASED_AMOUNT"])
            # else:
            #     putils.addPortalMessage(MESSAGES["CART_ADDED_PRODUCT"])

            url = "%s/added-to-cart" % shop.absolute_url()
            self.context.request.response.redirect(url)
Пример #21
0
    def _refreshCart(self):
        """
        """
        customer = ICustomerManagement(self.context).getAuthenticatedCustomer()

        cart = ICartManagement(self.context).getCart()
        if cart is None:
            return

        # Collect cart item properties for lookup
        selected_properties = {}
        for key, value in self.context.request.items():
            if key.startswith("property_"):
                property_id, cart_item_id = key.split(":")
                property_id = property_id[42:]

                if selected_properties.has_key(cart_item_id) == False:
                    selected_properties[cart_item_id] = []

                selected_properties[cart_item_id].append({
                    "id":
                    property_id,
                    "selected_option":
                    value
                })

        im = IItemManagement(cart)

        total_items = 0
        i = 1
        for cart_item in im.getItems():
            ci = "cart_item_%s" % i
            amount = self.context.REQUEST.get(ci)

            try:
                amount = int(amount)
            except ValueError:
                continue

            if amount < 0:
                continue

            if amount == 0:
                im.deleteItemByOrd(i - 1)
            else:
                cart_item.setAmount(amount)
            i += 1

            # Set properties
            product = cart_item.getProduct()
            if IProductVariant.providedBy(product):
                product = product.aq_inner.aq_parent
                pvm = IProductVariantsManagement(product)

                # We need the properties also as dict to get the selected
                # variant. Feels somewhat dirty. TODO: Try to unify the data
                # model for properties.
                properties = {}
                for property in selected_properties[cart_item.getId()]:
                    properties[property["id"]] = property["selected_option"]

                variant = pvm.getSelectedVariant(properties)
                cart_item.setProduct(variant)

                # TODO: At the moment we have to set the properties of the cart
                # item too. This is used in checkout-order-preview. Think about
                # to get rid of this because the properties are already available
                # in the variant.
                cart_item.setProperties(selected_properties[cart_item.getId()])

            else:
                if selected_properties.has_key(cart_item.getId()):
                    cart_item.setProperties(
                        selected_properties[cart_item.getId()])

        # Set selected country global and within current selected invoice
        # address. Why? If a customer delete all addresses the current selected
        # country is still saved global and can be used to calculate the
        # shipping price.
        selected_country = safe_unicode(self.request.get("selected_country"))
        customer.selected_country = selected_country
        #invoice_address = IAddressManagement(customer).getInvoiceAddress()
        #if invoice_address is not None:
        #    invoice_address.country = selected_country
        shipping_address = IAddressManagement(customer).getShippingAddress()
        if shipping_address is not None:
            shipping_address.country = queryUtility(IIDNormalizer).normalize(
                selected_country)

        shop = IShopManagement(self.context).getShop()
        shipping_methods = IShippingMethodManagement(shop).getShippingMethods(
            check_validity=True)
        shipping_methods_ids = [sm.getId() for sm in shipping_methods]
        selected_shipping_method = self.request.get("selected_shipping_method")

        # Set selected shipping method
        if selected_shipping_method in shipping_methods_ids:
            customer.selected_shipping_method = \
                safe_unicode(self.request.get("selected_shipping_method"))
        else:
            customer.selected_shipping_method = shipping_methods_ids[0]

        # Set selected payment method type
        customer.selected_payment_method = \
            safe_unicode(self.request.get("selected_payment_method"))

        # Set selected VAT registration
        selected_vat_country = safe_unicode(
            self.request.get("selected_vat_country"))
        selected_vat_number = safe_unicode(
            self.request.get("selected_vat_number"))
        if selected_vat_country == "" or selected_vat_country is None or selected_vat_number is None:
            customer.vatreg = None
        elif selected_vat_country == "XX":
            customer.vatreg = selected_vat_country
        else:
            customer.vatreg = selected_vat_country + selected_vat_number
Пример #22
0
    def _refreshCart(self):
        """
        """            
        customer = ICustomerManagement(self.context).getAuthenticatedCustomer()
        
        cart = ICartManagement(self.context).getCart()
        if cart is None:
            return

        # Collect cart item properties for lookup
        selected_properties = {}
        for key, value in self.context.request.items():
            if key.startswith("property_"):
                property_id, cart_item_id = key.split(":")
                property_id = property_id[42:]

                if selected_properties.has_key(cart_item_id) == False:
                    selected_properties[cart_item_id] = []

                selected_properties[cart_item_id].append({
                    "id" : property_id,
                    "selected_option" : value})
        
        im = IItemManagement(cart)
        
        total_items = 0
        i = 1
        for cart_item in im.getItems():
            ci = "cart_item_%s" % i
            amount = self.context.REQUEST.get(ci)
                        
            try:
                amount = int(amount)
            except ValueError:
                continue
            
            if amount < 0:
                continue
                    
            if amount == 0:
                im.deleteItemByOrd(i-1)
            else:    
                cart_item.setAmount(amount)
            i += 1

            # Set properties
            product = cart_item.getProduct()
            if IProductVariant.providedBy(product):
                product = product.aq_inner.aq_parent
                pvm = IProductVariantsManagement(product)
                
                # We need the properties also as dict to get the selected 
                # variant. Feels somewhat dirty. TODO: Try to unify the data 
                # model for properties.
                properties = {}
                for property in selected_properties[cart_item.getId()]:
                    properties[property["id"]] = property["selected_option"]                    
                    
                variant = pvm.getSelectedVariant(properties)
                cart_item.setProduct(variant)
                
                # TODO: At the moment we have to set the properties of the cart
                # item too. This is used in checkout-order-preview. Think about 
                # to get rid of this because the properties are already available 
                # in the variant.
                cart_item.setProperties(selected_properties[cart_item.getId()])
                
            else:
                if selected_properties.has_key(cart_item.getId()):
                    cart_item.setProperties(selected_properties[cart_item.getId()])
                    
        # Set selected country global and within current selected invoice 
        # address. Why? If a customer delete all addresses the current selected 
        # country is still saved global and can be used to calculate the 
        # shipping price.        
        selected_country = safe_unicode(self.request.get("selected_country"))
        customer.selected_country = selected_country
        #invoice_address = IAddressManagement(customer).getInvoiceAddress()
        #if invoice_address is not None:
        #    invoice_address.country = selected_country
        shipping_address = IAddressManagement(customer).getShippingAddress()
        if shipping_address is not None:
            shipping_address.country = queryUtility(IIDNormalizer).normalize(selected_country)

        shop = IShopManagement(self.context).getShop()
        shipping_methods = IShippingMethodManagement(shop).getShippingMethods(check_validity=True)
        shipping_methods_ids = [sm.getId() for sm in shipping_methods]
        selected_shipping_method = self.request.get("selected_shipping_method")

        # Set selected shipping method
        if selected_shipping_method in shipping_methods_ids:
            customer.selected_shipping_method = \
                safe_unicode(self.request.get("selected_shipping_method"))
        else:
            customer.selected_shipping_method = shipping_methods_ids[0]

        # Set selected payment method type
        customer.selected_payment_method = \
            safe_unicode(self.request.get("selected_payment_method"))
        
        # Set selected VAT registration
        selected_vat_country = safe_unicode(self.request.get("selected_vat_country"))
        selected_vat_number  = safe_unicode(self.request.get("selected_vat_number"))
        if selected_vat_country == "" or selected_vat_country is None or selected_vat_number is None:
            customer.vatreg = None
        elif selected_vat_country == "XX":
            customer.vatreg = selected_vat_country
        else:
            customer.vatreg = selected_vat_country + selected_vat_number
Пример #23
0
    def _getPropertiesForVariants(self):
        """
        """
        u = queryUtility(INumberConverter)
        cm = ICurrencyManagement(self.context)

        selected_options = {}
        for name, value in self.request.items():
            if name.startswith("property"):
                if len(name) > 42:
                    selected_options[name[42:]] = value
                else:
                    selected_options[name[9:]] = value

        # If nothing is selected we select the default variant
        if selected_options == {}:
            pvm = IProductVariantsManagement(self.context)
            default_variant = pvm.getDefaultVariant()

            # If there is no default variant return empty list
            if default_variant is None:
                return []

            for property in default_variant.getForProperties():
                name, value = property.split(":")
                selected_options[name] = value

        pm = IPropertyManagement(self.context)

        result = []
        for property in pm.getProperties():

            # Only properties with at least one option are displayed.
            if len(property.getOptions()) == 0:
                continue

            options = []
            for option in property.getOptions():

                # generate value string
                option_id    = option["id"]
                option_name  = option["name"]
                # option_price = option["price"]
                # option_price = u.stringToFloat(option_price)
                # option_price = cm.priceToString(option_price, "long", "after")
                # content = "%s %s" % (option_name, option_price)
                content = option_name

                # is option selected?
                selected_option = selected_options.get(property.getId(), "")
                selected = option_id == selected_option

                options.append({
                    "id"       : option_id,
                    "title"    : content,
                    "selected" : selected,
                })

            result.append({
                "id"      : "property_%s_%s" % (self.context.UID(), property.getId()),
                "title"   : property.Title(),
                "options" : options,
            })

        return result