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
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)
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(), }
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()
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
def getProperties(self): """ """ pvm = IProductVariantsManagement(self.context) if pvm.hasVariants(): return self._getPropertiesForVariants() else: return self._getPropertiesForConfiguration()
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()
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)
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)
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
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__()
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(), }
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
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
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)
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
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
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