def __call__(self): self.install_upgrade_profile() for item in self.objects({"portal_type": "ShopItem"}, "Migrate variations storage"): varConf = IVariationConfig(item) item_data = varConf.getVariationDict() varConf.updateVariationConfig(item_data)
def _parse_edit_variations_form(self): """Parses the form the user submitted when editing variations, and returns a dictionary that contains the variation data. """ form = self.request.form variation_config = IVariationConfig(self.context) variation_data = {} def _parse_data(variation_code): data = {} data['active'] = bool(form.get("%s-active" % variation_code)) if data['active']: # TODO: Handle decimal more elegantly price = form.get("%s-price" % variation_code) try: p = int(price) # Create a tuple of ints from string digits = tuple([int(i) for i in list(str(p))]) + (0, 0) data['price'] = Decimal((0, digits, -2)) except ValueError: if not price == "": data['price'] = Decimal(price) else: data['price'] = Decimal("0.00") data['skuCode'] = form.get("%s-skuCode" % variation_code) data['description'] = form.get("%s-description" % variation_code) # At this point the form has already been validated, # so uniqueness of sku codes is ensured data['hasUniqueSKU'] = True return data if len(variation_config.getVariationAttributes()) == 1: # One variation attribute for i, var1_value in enumerate(variation_config.getVariation1Values()): variation_code = 'var-%s' % i variation_data[variation_code] = _parse_data(variation_code) else: # Two variation attributes for i, var1_value in enumerate(variation_config.getVariation1Values()): for j, var2_value in enumerate(variation_config.getVariation2Values()): variation_code = 'var-%s-%s' % (i, j) variation_data[variation_code] = _parse_data(variation_code) return variation_data
def getItemDatas(self): """Returns a dictionary of an item's properties to be used in templates. If the item has variations, the variation config is also included. """ results = [] for item in self.getItems(): assert(IShopItem.providedBy(item)) varConf = IVariationConfig(item) has_variations = varConf.hasVariations() image = item.getField('image') if image and image.get_size(item): hasImage = True tag = image.tag(item, scale='mini') else: hasImage = False tag = None if has_variations: skuCode = None price = None else: varConf = None skuCode = item.Schema().getField('skuCode').get(item) price = item.Schema().getField('price').get(item) results.append( dict( item = item, title = item.Title(), description = item.Description(), url = item.absolute_url(), hasImage = hasImage, imageTag = tag, variants = None, skuCode = skuCode, price = price, showPrice = item.getField('showPrice').get(item), unit=item.getField('unit').get(item), uid = item.UID(), varConf = varConf, hasVariations = has_variations, selectable_dimensions = item.getSelectableDimensions())) return results
def SearchableText(self): """ Make variations searchable. """ data = super(ShopItem, self).SearchableText() var_conf = IVariationConfig(self) variation_details = [] if var_conf.hasVariations(): for variation in var_conf.getVariationDict().values(): if not variation['active']: continue variation_details.append(variation['description']) variation_details.append(variation['skuCode']) return ' '.join([ data, ' '.join(self.getVariation1_values()), ' '.join(self.getVariation2_values()), ' '.join(variation_details), self.getSkuCode() ])
def _parse_edit_variations_form(self): """Parses the form the user submitted when editing variations, and returns a dictionary that contains the variation data. """ form = self.request.form variation_config = IVariationConfig(self.context) variation_data = {} def _parse_data(variation_code): data = {} data['active'] = bool(form.get("%s-active" % variation_code)) if data['active']: # TODO: Handle decimal more elegantly price = form.get("%s-price" % variation_code) try: p = int(price) # Create a tuple of ints from string digits = tuple([int(i) for i in list(str(p))]) + (0, 0) data['price'] = Decimal((0, digits, -2)) except ValueError: if not price == "": data['price'] = Decimal(price) else: data['price'] = Decimal("0.00") data['skuCode'] = form.get("%s-skuCode" % variation_code) data['description'] = form.get("%s-description" % variation_code) # At this point the form has already been validated, # so uniqueness of sku codes is ensured data['hasUniqueSKU'] = True return data if len(variation_config.getVariationAttributes()) == 1: # One variation attribute for i, var1_value in enumerate( variation_config.getVariation1Values()): variation_code = 'var-%s' % i variation_data[variation_code] = _parse_data(variation_code) else: # Two variation attributes for i, var1_value in enumerate( variation_config.getVariation1Values()): for j, var2_value in enumerate( variation_config.getVariation2Values()): variation_code = 'var-%s-%s' % (i, j) variation_data[variation_code] = _parse_data( variation_code) return variation_data
def __call__(self): """Migrates all items """ catalog = getToolByName(self.context, 'portal_catalog') normalize = getUtility(IIDNormalizer).normalize response = "" stats = {} items = catalog(portal_type="ShopItem") for item in items: obj = item.getObject() stats[obj.UID()] = {'status': 'UNKNOWN', 'result': 'UNKNOWN'} var_conf = IVariationConfig(obj) # Skip broken OrderedDict items var_dict = var_conf.getVariationDict() if str(type(var_dict)) == "<class 'zc.dict.dict.OrderedDict'>": status = "SKIPPED: Broken OrderedDict Item '%s' at '%s'" % (obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = {'status': 'SKIPPED', 'result': 'SUCCESS'} continue varAttrs = var_conf.getVariationAttributes() num_variations = len(varAttrs) if num_variations == 0: # No migration needed stats[obj.UID()] = {'status': 'NO_MIGRATION_NEEDED', 'result': 'SUCCESS'} continue # Migrate items with 2 variations if num_variations == 2: migrated = True # Create mapping from old to new keys mapping = {} for i, v1 in enumerate(var_conf.getVariation1Values()): for j, v2 in enumerate(var_conf.getVariation2Values()): vkey = "%s-%s" % (normalize(v1), normalize(v2)) vcode = "var-%s-%s" % (i, j) mapping[vkey] = vcode # Check if item needs to be migrated for key in var_dict.keys(): if key in mapping.keys(): migrated = False if migrated: # Already migrated stats[obj.UID()] = {'status': 'ALREADY_MIGRATED', 'result': 'SUCCESS'} else: # Migrate the item print "Migrating %s..." % obj.Title() for vkey in mapping.keys(): vcode = mapping[vkey] try: # Store data with new vcode var_dict[vcode] = var_dict[vkey] del var_dict[vkey] var_conf.updateVariationConfig(var_dict) transaction.commit() stats[obj.UID()] = {'status': 'MIGRATED', 'result': 'SUCCESS'} except KeyError: status = "FAILED: Migration of item '%s' at '%s' failed!" % (obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = {'status': 'FAILED', 'result': 'FAILED'} break if stats[obj.UID()]['status'] == 'MIGRATED': status = "MIGRATED: Item '%s' at '%s'" % (obj.Title(), obj.absolute_url()) response += status + "\n" print status # Migrate items with 1 variation if num_variations == 1: migrated = True # Create mapping from old to new keys mapping = {} for i, v1 in enumerate(var_conf.getVariation1Values()): vkey = normalize(v1) vcode = "var-%s" % i mapping[vkey] = vcode # Check if item needs to be migrated for key in var_dict.keys(): if key in mapping.keys(): migrated = False if migrated: # Already migrated stats[obj.UID()] = {'status': 'ALREADY_MIGRATED', 'result': 'SUCCESS'} else: # Migrate this item print "Migrating %s..." % obj.Title() for vkey in mapping.keys(): vcode = mapping[vkey] try: # Store data with new vcode var_dict[vcode] = var_dict[vkey] del var_dict[vkey] var_conf.updateVariationConfig(var_dict) transaction.commit() stats[obj.UID()] = {'status': 'MIGRATED', 'result': 'SUCCESS'} except KeyError: status = "FAILED: Migration of item '%s' at '%s' failed!" % (obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = {'status': 'FAILED', 'result': 'FAILED'} break if stats[obj.UID()]['status'] == 'MIGRATED': status = "MIGRATED: Item '%s' at '%s'" % (obj.Title(), obj.absolute_url()) response += status + "\n" print status total = len(items) migrated = len([stats[k] for k in stats if stats[k]['status'] == 'MIGRATED']) skipped = len([stats[k] for k in stats if stats[k]['status'] == 'SKIPPED']) failed = len([stats[k] for k in stats if stats[k]['status'] == 'FAILED']) no_migration_needed = len([stats[k] for k in stats if stats[k]['status'] == 'NO_MIGRATION_NEEDED']) already = len([stats[k] for k in stats if stats[k]['status'] == 'ALREADY_MIGRATED']) summary = "TOTAL: %s MIGRATED: %s SKIPPED: %s "\ "FAILED: %s NO MIGRATION NEEDED: %s ALREADY_MIGRATED: %s" % (total, migrated, skipped, failed, no_migration_needed, already) response = "%s\n\n%s" % (summary, response) return response
def __call__(self): """ Self-submitting form that displays ShopItem Variations and updates them """ form = self.request.form if form.get('remove_level'): variation_config = IVariationConfig(self.context) variation_config.remove_level() if form.get('reduce_level'): variation_config = IVariationConfig(self.context) variation_config.reduce_level() if form.get('add_level'): variation_config = IVariationConfig(self.context) variation_config.add_level() if form.get('addvalue'): fn = None idx_and_pos = form.get('addvalue') idx, pos = idx_and_pos.split('-') idx = int(idx) pos = int(pos) + 1 if idx == 0: fn = 'variation1_values' elif idx == 1: fn = 'variation2_values' variation_config = IVariationConfig(self.context) values = list(self.context.getField(fn).get(self.context)) var_dict = variation_config.getVariationDict() new_var_dict = {} pps = getMultiAdapter((self.context, self.request), name='plone_portal_state') language = pps.language() new_description = translate(_('label_new_description', default=u'New description'), domain='ftw.shop', context=self.context, target_language=language) DEFAULT_VARDATA = {'active':True, 'price': '0.00', 'skuCode': '99999', 'description': new_description} if len(variation_config.getVariationAttributes()) == 2: values1 = list(self.context.getField('variation1_values').get(self.context)) values2 = list(self.context.getField('variation2_values').get(self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} if idx == 0: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if i >= pos: new_vcode = "var-%s-%s" % (i + 1, j) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode elif idx == 1: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if j >= pos: new_vcode = "var-%s-%s" % (i, j + 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # Now add some default variation data for the value just added if idx == 0: for j in range(len(values2)): vcode = "var-%s-%s" % (pos, j) new_var_dict[vcode] = DEFAULT_VARDATA elif idx == 1: for i in range(len(values1)): vcode = "var-%s-%s" % (i, pos) new_var_dict[vcode] = DEFAULT_VARDATA elif len(variation_config.getVariationAttributes()) == 1: assert(idx == 0) values1 = list(self.context.getField('variation1_values').get(self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} for i in range(len(values1)): old_vcode = "var-%s" % (i) if i >= pos: new_vcode = "var-%s" % (i + 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # Now add some default variation data for the value just added vcode = "var-%s" % pos new_var_dict[vcode] = DEFAULT_VARDATA # Finally purge and update the var_dict variation_config.purge_dict() variation_config.updateVariationConfig(new_var_dict) pps = getMultiAdapter((self.context, self.request), name='plone_portal_state') language = pps.language() new_value = translate(_('label_new_value', default=u'New value'), domain='ftw.shop', context=self.context, target_language=language) values.insert(pos, new_value) self.context.getField(fn).set(self.context, values) if form.get('delvalue'): fn = None idx_and_pos = form.get('delvalue') idx, pos = idx_and_pos.split('-') idx = int(idx) pos = int(pos) if idx == 0: fn = 'variation1_values' elif idx == 1: fn = 'variation2_values' values = list(self.context.getField(fn).get(self.context)) variation_config = IVariationConfig(self.context) var_dict = variation_config.getVariationDict() new_var_dict = {} if len(variation_config.getVariationAttributes()) == 2: values1 = list(self.context.getField('variation1_values').get(self.context)) values2 = list(self.context.getField('variation2_values').get(self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} if idx == 0: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if i > pos: new_vcode = "var-%s-%s" % (i - 1, j) code_map[old_vcode] = new_vcode elif i == pos: code_map[old_vcode] = None else: code_map[old_vcode] = old_vcode elif idx == 1: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if j > pos: new_vcode = "var-%s-%s" % (i, j - 1) code_map[old_vcode] = new_vcode elif j == pos: code_map[old_vcode] = None else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] elif len(variation_config.getVariationAttributes()) == 1: assert(idx == 0) values1 = list(self.context.getField('variation1_values').get(self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} for i in range(len(values1)): old_vcode = "var-%s" % (i) if i >= pos: new_vcode = "var-%s" % (i - 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # # Finally purge and update the var_dict variation_config.purge_dict() variation_config.updateVariationConfig(new_var_dict) values.pop(int(pos)) self.context.getField(fn).set(self.context, values) if form.get('update_structure'): var_config = IVariationConfig(self.context) vattr0 = form.get('vattr-0', None) vattr1 = form.get('vattr-1', None) if len(var_config.getVariationAttributes()) >= 1: self.context.getField('variation1_attribute').set(self.context, vattr0) new_values = [] for i in range(len(var_config.getVariation1Values())): new_value = form.get('vvalue-%s-%s' % (0, i)) new_values.append(new_value) self.context.getField('variation1_values').set(self.context, new_values) if len(var_config.getVariationAttributes()) >= 2: self.context.getField('variation2_attribute').set(self.context, vattr1) new_values = [] for j in range(len(var_config.getVariation2Values())): new_value = form.get('vvalue-%s-%s' % (1, j)) new_values.append(new_value) self.context.getField('variation2_values').set(self.context, new_values) # Make sure we had a proper form submit, not just a GET request submitted = form.get('form.submitted', False) if submitted: variation_config = IVariationConfig(self.context) edited_var_data = self._parse_edit_variations_form() variation_config.updateVariationConfig(edited_var_data) IStatusMessage(self.request).addStatusMessage( _(u'msg_variations_saved', default=u"Variations saved."), type="info") self.request.RESPONSE.redirect(self.context.absolute_url()) return self.template()
def _add_item(self, skuCode=None, quantity=1, var1choice=None, var2choice=None): """ Add item to cart """ context = aq_inner(self.context) varConf = IVariationConfig(self.context) # get current items in cart session = self.request.SESSION cart_items = session.get(CART_KEY, {}) variation_code = varConf.variation_code(var1choice, var2choice) # We got no skuCode, so look it up by variation key if not skuCode: skuCode = varConf.sku_code(var1choice, var2choice) item_key = varConf.key(var1choice, var2choice) item = cart_items.get(item_key, None) item_title = context.Title() quantity = int(quantity) vat_rate = Decimal(context.getField('vat').get(context)) supplier_name, supplier_email = self._get_supplier_info(context) has_variations = varConf.hasVariations() if has_variations: variation_dict = varConf.getVariationDict() if not variation_dict[variation_code]['active']: # Item is disabled return False variation_pretty_name = varConf.getPrettyName(variation_code) item_title = '%s - %s' % (context.Title(), variation_pretty_name) price = Decimal(variation_dict[variation_code]['price']) # add item to cart if item is None: item = { 'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': str(price * quantity), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'variation_code': variation_code, 'vat_rate': vat_rate, 'vat_amount': str(calc_vat(vat_rate, price)) } # item already in cart, update quantity else: item['quantity'] = item.get('quantity', 0) + quantity item['total'] = str(item['quantity'] * price) item['vat_amount'] = str(calc_vat(vat_rate, price, quantity)) else: price = Decimal(context.Schema().getField('price').get(context)) # add item to cart if item is None: item = { 'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': str(price * quantity), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'vat_rate': vat_rate, 'vat_amount': str(calc_vat(vat_rate, price)) } # item already in cart, update quantitiy else: item['quantity'] = item.get('quantity', 0) + quantity item['total'] = str(item['quantity'] * price) item['vat_amount'] = str(calc_vat(vat_rate, price, quantity)) # store cart in session cart_items[item_key] = item session[CART_KEY] = cart_items return True
def getVariationsConfig(self): """Returns the variation config for the item currently being viewed """ context = aq_inner(self.context) variation_config = IVariationConfig(context) return variation_config
def __call__(self): """Migrates all items """ catalog = getToolByName(self.context, 'portal_catalog') normalize = getUtility(IIDNormalizer).normalize response = "" stats = {} items = catalog(portal_type="ShopItem") for item in items: obj = item.getObject() stats[obj.UID()] = {'status': 'UNKNOWN', 'result': 'UNKNOWN'} var_conf = IVariationConfig(obj) # Skip broken OrderedDict items var_dict = var_conf.getVariationDict() if str(type(var_dict)) == "<class 'zc.dict.dict.OrderedDict'>": status = "SKIPPED: Broken OrderedDict Item '%s' at '%s'" % ( obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = {'status': 'SKIPPED', 'result': 'SUCCESS'} continue varAttrs = var_conf.getVariationAttributes() num_variations = len(varAttrs) if num_variations == 0: # No migration needed stats[obj.UID()] = { 'status': 'NO_MIGRATION_NEEDED', 'result': 'SUCCESS' } continue # Migrate items with 2 variations if num_variations == 2: migrated = True # Create mapping from old to new keys mapping = {} for i, v1 in enumerate(var_conf.getVariation1Values()): for j, v2 in enumerate(var_conf.getVariation2Values()): vkey = "%s-%s" % (normalize(v1), normalize(v2)) vcode = "var-%s-%s" % (i, j) mapping[vkey] = vcode # Check if item needs to be migrated for key in var_dict.keys(): if key in mapping.keys(): migrated = False if migrated: # Already migrated stats[obj.UID()] = { 'status': 'ALREADY_MIGRATED', 'result': 'SUCCESS' } else: # Migrate the item print "Migrating %s..." % obj.Title() for vkey in mapping.keys(): vcode = mapping[vkey] try: # Store data with new vcode var_dict[vcode] = var_dict[vkey] del var_dict[vkey] var_conf.updateVariationConfig(var_dict) transaction.commit() stats[obj.UID()] = { 'status': 'MIGRATED', 'result': 'SUCCESS' } except KeyError: status = "FAILED: Migration of item '%s' at '%s' failed!" % ( obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = { 'status': 'FAILED', 'result': 'FAILED' } break if stats[obj.UID()]['status'] == 'MIGRATED': status = "MIGRATED: Item '%s' at '%s'" % ( obj.Title(), obj.absolute_url()) response += status + "\n" print status # Migrate items with 1 variation if num_variations == 1: migrated = True # Create mapping from old to new keys mapping = {} for i, v1 in enumerate(var_conf.getVariation1Values()): vkey = normalize(v1) vcode = "var-%s" % i mapping[vkey] = vcode # Check if item needs to be migrated for key in var_dict.keys(): if key in mapping.keys(): migrated = False if migrated: # Already migrated stats[obj.UID()] = { 'status': 'ALREADY_MIGRATED', 'result': 'SUCCESS' } else: # Migrate this item print "Migrating %s..." % obj.Title() for vkey in mapping.keys(): vcode = mapping[vkey] try: # Store data with new vcode var_dict[vcode] = var_dict[vkey] del var_dict[vkey] var_conf.updateVariationConfig(var_dict) transaction.commit() stats[obj.UID()] = { 'status': 'MIGRATED', 'result': 'SUCCESS' } except KeyError: status = "FAILED: Migration of item '%s' at '%s' failed!" % ( obj.Title(), obj.absolute_url()) response += status + "\n" print status stats[obj.UID()] = { 'status': 'FAILED', 'result': 'FAILED' } break if stats[obj.UID()]['status'] == 'MIGRATED': status = "MIGRATED: Item '%s' at '%s'" % ( obj.Title(), obj.absolute_url()) response += status + "\n" print status total = len(items) migrated = len( [stats[k] for k in stats if stats[k]['status'] == 'MIGRATED']) skipped = len( [stats[k] for k in stats if stats[k]['status'] == 'SKIPPED']) failed = len( [stats[k] for k in stats if stats[k]['status'] == 'FAILED']) no_migration_needed = len([ stats[k] for k in stats if stats[k]['status'] == 'NO_MIGRATION_NEEDED' ]) already = len([ stats[k] for k in stats if stats[k]['status'] == 'ALREADY_MIGRATED' ]) summary = "TOTAL: %s MIGRATED: %s SKIPPED: %s "\ "FAILED: %s NO MIGRATION NEEDED: %s ALREADY_MIGRATED: %s" % (total, migrated, skipped, failed, no_migration_needed, already) response = "%s\n\n%s" % (summary, response) return response
def __call__(self): """ Self-submitting form that displays ShopItem Variations and updates them """ form = self.request.form if form.get('remove_level'): variation_config = IVariationConfig(self.context) variation_config.remove_level() if form.get('reduce_level'): variation_config = IVariationConfig(self.context) variation_config.reduce_level() if form.get('add_level'): variation_config = IVariationConfig(self.context) variation_config.add_level() if form.get('addvalue'): fn = None idx_and_pos = form.get('addvalue') idx, pos = idx_and_pos.split('-') idx = int(idx) pos = int(pos) + 1 if idx == 0: fn = 'variation1_values' elif idx == 1: fn = 'variation2_values' variation_config = IVariationConfig(self.context) values = list(self.context.getField(fn).get(self.context)) var_dict = variation_config.getVariationDict() new_var_dict = {} pps = getMultiAdapter((self.context, self.request), name='plone_portal_state') language = pps.language() new_description = translate(_('label_new_description', default=u'New description'), domain='ftw.shop', context=self.context, target_language=language) DEFAULT_VARDATA = { 'active': True, 'price': '0.00', 'skuCode': '99999', 'description': new_description } if len(variation_config.getVariationAttributes()) == 2: values1 = list( self.context.getField('variation1_values').get( self.context)) values2 = list( self.context.getField('variation2_values').get( self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} if idx == 0: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if i >= pos: new_vcode = "var-%s-%s" % (i + 1, j) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode elif idx == 1: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if j >= pos: new_vcode = "var-%s-%s" % (i, j + 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # Now add some default variation data for the value just added if idx == 0: for j in range(len(values2)): vcode = "var-%s-%s" % (pos, j) new_var_dict[vcode] = DEFAULT_VARDATA elif idx == 1: for i in range(len(values1)): vcode = "var-%s-%s" % (i, pos) new_var_dict[vcode] = DEFAULT_VARDATA elif len(variation_config.getVariationAttributes()) == 1: assert (idx == 0) values1 = list( self.context.getField('variation1_values').get( self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} for i in range(len(values1)): old_vcode = "var-%s" % (i) if i >= pos: new_vcode = "var-%s" % (i + 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # Now add some default variation data for the value just added vcode = "var-%s" % pos new_var_dict[vcode] = DEFAULT_VARDATA # Finally purge and update the var_dict variation_config.purge_dict() variation_config.updateVariationConfig(new_var_dict) pps = getMultiAdapter((self.context, self.request), name='plone_portal_state') language = pps.language() new_value = translate(_('label_new_value', default=u'New value'), domain='ftw.shop', context=self.context, target_language=language) values.insert(pos, new_value) self.context.getField(fn).set(self.context, values) if form.get('delvalue'): fn = None idx_and_pos = form.get('delvalue') idx, pos = idx_and_pos.split('-') idx = int(idx) pos = int(pos) if idx == 0: fn = 'variation1_values' elif idx == 1: fn = 'variation2_values' values = list(self.context.getField(fn).get(self.context)) variation_config = IVariationConfig(self.context) var_dict = variation_config.getVariationDict() new_var_dict = {} if len(variation_config.getVariationAttributes()) == 2: values1 = list( self.context.getField('variation1_values').get( self.context)) values2 = list( self.context.getField('variation2_values').get( self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} if idx == 0: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if i > pos: new_vcode = "var-%s-%s" % (i - 1, j) code_map[old_vcode] = new_vcode elif i == pos: code_map[old_vcode] = None else: code_map[old_vcode] = old_vcode elif idx == 1: for i in range(len(values1)): for j in range(len(values2)): old_vcode = "var-%s-%s" % (i, j) if j > pos: new_vcode = "var-%s-%s" % (i, j - 1) code_map[old_vcode] = new_vcode elif j == pos: code_map[old_vcode] = None else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] elif len(variation_config.getVariationAttributes()) == 1: assert (idx == 0) values1 = list( self.context.getField('variation1_values').get( self.context)) # Create a dict mapping old combination indexes to the new ones code_map = {} for i in range(len(values1)): old_vcode = "var-%s" % (i) if i >= pos: new_vcode = "var-%s" % (i - 1) code_map[old_vcode] = new_vcode else: code_map[old_vcode] = old_vcode # Based on the code map, reorder the var_dict for old_vcode in code_map.keys(): new_vcode = code_map[old_vcode] new_var_dict[new_vcode] = var_dict[old_vcode] # # Finally purge and update the var_dict variation_config.purge_dict() variation_config.updateVariationConfig(new_var_dict) values.pop(int(pos)) self.context.getField(fn).set(self.context, values) if form.get('update_structure'): var_config = IVariationConfig(self.context) vattr0 = form.get('vattr-0', None) vattr1 = form.get('vattr-1', None) if len(var_config.getVariationAttributes()) >= 1: self.context.getField('variation1_attribute').set( self.context, vattr0) new_values = [] for i in range(len(var_config.getVariation1Values())): new_value = form.get('vvalue-%s-%s' % (0, i)) new_values.append(new_value) self.context.getField('variation1_values').set( self.context, new_values) if len(var_config.getVariationAttributes()) >= 2: self.context.getField('variation2_attribute').set( self.context, vattr1) new_values = [] for j in range(len(var_config.getVariation2Values())): new_value = form.get('vvalue-%s-%s' % (1, j)) new_values.append(new_value) self.context.getField('variation2_values').set( self.context, new_values) # Make sure we had a proper form submit, not just a GET request submitted = form.get('form.submitted', False) if submitted: variation_config = IVariationConfig(self.context) edited_var_data = self._parse_edit_variations_form() variation_config.updateVariationConfig(edited_var_data) IStatusMessage(self.request).addStatusMessage(_( u'msg_variations_saved', default=u"Variations saved."), type="info") self.request.RESPONSE.redirect(self.context.absolute_url()) return self.template()
def afterSetUp(self): provideAdapter(FakeMailHostAdapter, (Interface, ), IMailHostAdapter) # Set up sessioning objects ztc.utils.setupCoreSessions(self.app) # Create an initial browser_id by requesting it bid_manager = getToolByName(self.app, 'browser_id_manager') bid_manager.getBrowserId() self.workflow = getToolByName(self.portal, 'portal_workflow') self.acl_users = getToolByName(self.portal, 'acl_users') self.types = getToolByName(self.portal, 'portal_types') self.setRoles(('Manager',)) # Use helper method to set up shop root at portal.shop init_shop = getMultiAdapter((self.portal, self.portal.REQUEST), Interface, 'initialize-shop-structure') init_shop() # Create a shop category self.portal.shop.invokeFactory("ShopCategory", "products") self.portal.shop.products.reindexObject() # Create a Shop Item with no variations self.portal.shop.products.invokeFactory('ShopItem', 'movie') self.movie = self.portal.shop.products['movie'] self.movie.getField('skuCode').set(self.movie, "12345") self.movie.getField('price').set(self.movie, "7.15") self.movie.getField('showPrice').set(self.movie, True) self.movie.getField('title').set(self.movie, "A Movie") self.movie.getField('description').set(self.movie, "A Shop Item with no variations") self.movie.getField('selectable_dimensions').set(self.movie, 'length_width_mm_mm2') # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.movie, self.portal.REQUEST) zope.event.notify(event) self.movie.reindexObject() self.movie_vc = IVariationConfig(self.movie) # Create a Shop Item with one variation self.portal.shop.products.invokeFactory('ShopItem', 'book') self.book = self.portal.shop.products['book'] self.book.getField('title').set(self.book, 'Professional Plone Development') self.book.getField('description').set(self.book, 'A Shop Item with one variation') self.book.getField('variation1_attribute').set(self.book, 'Cover') self.book.getField('variation1_values').set(self.book, ['Hardcover', 'Paperback']) # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.book, self.portal.REQUEST) zope.event.notify(event) self.book.reindexObject() self.book_vc = IVariationConfig(self.book) book_var_dict = { 'var-Hardcover': {'active': True, 'price': Decimal('1.00'), 'skuCode': 'b11', 'description': 'A hard and durable cover', 'hasUniqueSKU': True}, 'var-Paperback': {'active': True, 'price': Decimal('2.00'), 'skuCode': 'b22', 'description': 'A less durable but cheaper cover', 'hasUniqueSKU': True}, } self.book_vc.updateVariationConfig(book_var_dict) # Create a Shop Item with two variations self.portal.shop.products.invokeFactory('ShopItem', 't-shirt') self.tshirt = self.portal.shop.products['t-shirt'] self.tshirt.getField('title').set(self.tshirt, 'A T-Shirt') self.tshirt.getField('description').set(self.tshirt, 'A Shop Item with two variations') self.tshirt.getField('variation1_attribute').set(self.tshirt, 'Color') self.tshirt.getField('variation1_values').set(self.tshirt, ['Red', 'Green', 'Blue']) self.tshirt.getField('variation2_attribute').set(self.tshirt, 'Size') self.tshirt.getField('variation2_values').set(self.tshirt, ['S', 'M', 'L']) # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.tshirt, self.portal.REQUEST) zope.event.notify(event) self.tshirt.reindexObject() self.tshirt_vc = IVariationConfig(self.tshirt) tshirt_var_dict = { 'var-Red-S': {'active': True, 'price': Decimal('1.00'), 'skuCode': '11', 'description': '', 'hasUniqueSKU': True}, 'var-Red-M': {'active': True, 'price': Decimal('2.00'), 'skuCode': '22', 'description': '', 'hasUniqueSKU': True}, 'var-Red-L': {'active': True, 'price': Decimal('3.00'), 'skuCode': '33', 'description': '', 'hasUniqueSKU': True}, 'var-Green-S': {'active': True, 'price': Decimal('4.00'), 'skuCode': '44', 'description': '', 'hasUniqueSKU': True}, 'var-Green-M': {'active': True, 'price': Decimal('5.00'), 'skuCode': '55', 'description': '', 'hasUniqueSKU': True}, 'var-Green-L': {'active': True, 'price': Decimal('6.00'), 'skuCode': '66', 'description': '', 'hasUniqueSKU': True}, 'var-Blue-S': {'active': True, 'price': Decimal('7.00'), 'skuCode': '77', 'description': '', 'hasUniqueSKU': True}, 'var-Blue-M': {'active': True, 'price': Decimal('8.00'), 'skuCode': '88', 'description': '', 'hasUniqueSKU': True}, 'var-Blue-L': {'active': True, 'price': Decimal('9.00'), 'skuCode': '99', 'description': '', 'hasUniqueSKU': True}, } self.tshirt_vc.updateVariationConfig(tshirt_var_dict) # Create a subcategory below the shop root self.portal.shop.products.invokeFactory("ShopCategory", "subcategory") self.subcategory = self.portal.shop.products.subcategory # Fire ObjectInitializedEvent to add category to containing category event = ObjectInitializedEvent(self.subcategory, self.portal.REQUEST) zope.event.notify(event) self.setRoles(('Member',))
def _add_item(self, skuCode=None, quantity=1, var1choice=None, var2choice=None): """ Add item to cart """ context = aq_inner(self.context) varConf = IVariationConfig(self.context) # get current items in cart session = self.request.SESSION cart_items = session.get(CART_KEY, {}) variation_code = varConf.variation_code(var1choice, var2choice) # We got no skuCode, so look it up by variation key if not skuCode: skuCode = varConf.sku_code(var1choice, var2choice) item_key = varConf.key(var1choice, var2choice) item = cart_items.get(item_key, None) item_title = context.Title() quantity = int(quantity) vat_rate = Decimal(context.getField('vat').get(context)) supplier_name, supplier_email = self._get_supplier_info(context) has_variations = varConf.hasVariations() if has_variations: variation_dict = varConf.getVariationDict() if not variation_dict[variation_code]['active']: # Item is disabled return False variation_pretty_name = varConf.getPrettyName(variation_code) item_title = '%s - %s' % (context.Title(), variation_pretty_name) price = Decimal(variation_dict[variation_code]['price']) # add item to cart if item is None: item = {'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': str(price * quantity), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'variation_code': variation_code, 'vat_rate': vat_rate, 'vat_amount': str(calc_vat(vat_rate, price)) } # item already in cart, update quantity else: item['quantity'] = item.get('quantity', 0) + quantity item['total'] = str(item['quantity'] * price) item['vat_amount'] = str(calc_vat(vat_rate, price, quantity)) else: price = Decimal(context.Schema().getField('price').get(context)) # add item to cart if item is None: item = {'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': str(price * quantity), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'vat_rate': vat_rate, 'vat_amount': str(calc_vat(vat_rate, price)) } # item already in cart, update quantitiy else: item['quantity'] = item.get('quantity', 0) + quantity item['total'] = str(item['quantity'] * price) item['vat_amount'] = str(calc_vat(vat_rate, price, quantity)) # store cart in session cart_items[item_key] = item session[CART_KEY] = cart_items return True
def afterSetUp(self): provideAdapter(FakeMailHostAdapter, (Interface,), IMailHostAdapter) # Set up sessioning objects ztc.utils.setupCoreSessions(self.app) # Create an initial browser_id by requesting it bid_manager = getToolByName(self.app, "browser_id_manager") bid_manager.getBrowserId() self.workflow = getToolByName(self.portal, "portal_workflow") self.acl_users = getToolByName(self.portal, "acl_users") self.types = getToolByName(self.portal, "portal_types") self.setRoles(("Manager",)) # Use helper method to set up shop root at portal.shop init_shop = getMultiAdapter((self.portal, self.portal.REQUEST), Interface, "initialize-shop-structure") init_shop() # Create a shop category self.portal.shop.invokeFactory("ShopCategory", "products") self.portal.shop.products.reindexObject() # Create a Shop Item with no variations self.portal.shop.products.invokeFactory("ShopItem", "movie") self.movie = self.portal.shop.products["movie"] self.movie.getField("skuCode").set(self.movie, "12345") self.movie.getField("price").set(self.movie, "7.15") self.movie.getField("showPrice").set(self.movie, True) self.movie.getField("title").set(self.movie, "A Movie") self.movie.getField("description").set(self.movie, "A Shop Item with no variations") # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.movie, self.portal.REQUEST) zope.event.notify(event) self.movie.reindexObject() self.movie_vc = IVariationConfig(self.movie) # Create a Shop Item with one variation self.portal.shop.products.invokeFactory("ShopItem", "book") self.book = self.portal.shop.products["book"] self.book.getField("title").set(self.book, "Professional Plone Development") self.book.getField("description").set(self.book, "A Shop Item with one variation") self.book.getField("variation1_attribute").set(self.book, "Cover") self.book.getField("variation1_values").set(self.book, ["Hardcover", "Paperback"]) # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.book, self.portal.REQUEST) zope.event.notify(event) self.book.reindexObject() self.book_vc = IVariationConfig(self.book) book_var_dict = { "var-Hardcover": { "active": True, "price": Decimal("1.00"), "skuCode": "b11", "description": "A hard and durable cover", "hasUniqueSKU": True, }, "var-Paperback": { "active": True, "price": Decimal("2.00"), "skuCode": "b22", "description": "A less durable but cheaper cover", "hasUniqueSKU": True, }, } self.book_vc.updateVariationConfig(book_var_dict) # Create a Shop Item with two variations self.portal.shop.products.invokeFactory("ShopItem", "t-shirt") self.tshirt = self.portal.shop.products["t-shirt"] self.tshirt.getField("title").set(self.tshirt, "A T-Shirt") self.tshirt.getField("description").set(self.tshirt, "A Shop Item with two variations") self.tshirt.getField("variation1_attribute").set(self.tshirt, "Color") self.tshirt.getField("variation1_values").set(self.tshirt, ["Red", "Green", "Blue"]) self.tshirt.getField("variation2_attribute").set(self.tshirt, "Size") self.tshirt.getField("variation2_values").set(self.tshirt, ["S", "M", "L"]) # Fire ObjectInitializedEvent to add item to containing category event = ObjectInitializedEvent(self.tshirt, self.portal.REQUEST) zope.event.notify(event) self.tshirt.reindexObject() self.tshirt_vc = IVariationConfig(self.tshirt) tshirt_var_dict = { "var-Red-S": { "active": True, "price": Decimal("1.00"), "skuCode": "11", "description": "", "hasUniqueSKU": True, }, "var-Red-M": { "active": True, "price": Decimal("2.00"), "skuCode": "22", "description": "", "hasUniqueSKU": True, }, "var-Red-L": { "active": True, "price": Decimal("3.00"), "skuCode": "33", "description": "", "hasUniqueSKU": True, }, "var-Green-S": { "active": True, "price": Decimal("4.00"), "skuCode": "44", "description": "", "hasUniqueSKU": True, }, "var-Green-M": { "active": True, "price": Decimal("5.00"), "skuCode": "55", "description": "", "hasUniqueSKU": True, }, "var-Green-L": { "active": True, "price": Decimal("6.00"), "skuCode": "66", "description": "", "hasUniqueSKU": True, }, "var-Blue-S": { "active": True, "price": Decimal("7.00"), "skuCode": "77", "description": "", "hasUniqueSKU": True, }, "var-Blue-M": { "active": True, "price": Decimal("8.00"), "skuCode": "88", "description": "", "hasUniqueSKU": True, }, "var-Blue-L": { "active": True, "price": Decimal("9.00"), "skuCode": "99", "description": "", "hasUniqueSKU": True, }, } self.tshirt_vc.updateVariationConfig(tshirt_var_dict) # Create a subcategory below the shop root self.portal.shop.products.invokeFactory("ShopCategory", "subcategory") self.subcategory = self.portal.shop.products.subcategory # Fire ObjectInitializedEvent to add category to containing category event = ObjectInitializedEvent(self.subcategory, self.portal.REQUEST) zope.event.notify(event) self.setRoles(("Member",))
def _add_item(self, skuCode=None, quantity=1, var1choice=None, var2choice=None, dimensions=None): """ Add item to cart """ context = aq_inner(self.context) varConf = IVariationConfig(self.context) # get current items in cart session = self.request.SESSION cart_items = session.get(CART_KEY, OrderedDict()) variation_code = varConf.variation_code(var1choice, var2choice) # We got no skuCode, so look it up by variation key if not skuCode: skuCode = varConf.sku_code(var1choice, var2choice) item_key = self.get_item_key(self.context.UID(), variation_code, dimensions) item = cart_items.get(item_key, None) item_title = context.Title() quantity = int(quantity) vat_rate = Decimal(context.getField('vat').get(context)) supplier_name, supplier_email = self._get_supplier_info(context) if dimensions is None: dimensions = [] price_modifier = self.context.getPriceModifier() has_variations = varConf.hasVariations() if has_variations: variation_dict = varConf.getVariationDict() if not variation_dict[variation_code]['active']: # Item is disabled return False variation_pretty_name = varConf.getPrettyName(variation_code) item_title = '%s - %s' % (context.Title(), variation_pretty_name) price = Decimal(variation_dict[variation_code]['price']) price_per_item = self.calc_price_per_item(price, dimensions, price_modifier) # add item to cart if item is None: total = self.calc_item_total(price, quantity, dimensions, price_modifier) item = {'uid': self.context.UID(), 'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': '{:.2f}'.format(total), 'price_per_item': '{:.2f}'.format(price_per_item), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'variation_code': variation_code, 'vat_rate': vat_rate, 'vat_amount': str(self.calc_vat(vat_rate, total)), 'dimensions': dimensions, 'selectable_dimensions': context.getSelectableDimensions(), 'price_modifier': price_modifier } # item already in cart, update quantity else: item['quantity'] = item.get('quantity', 0) + quantity total = self.calc_item_total(price, item['quantity'], dimensions, price_modifier) item['dimensions'] = dimensions item['total'] = '{:.2f}'.format(total) item['price_per_item'] = '{:.2f}'.format(price_per_item) item['vat_amount'] = str(self.calc_vat(vat_rate, total)) else: price = Decimal(context.Schema().getField('price').get(context)) price_per_item = self.calc_price_per_item(price, dimensions, price_modifier) # add item to cart if item is None: total = self.calc_item_total(price, quantity, dimensions, price_modifier) item = {'uid': self.context.UID(), 'title': item_title, 'description': context.Description(), 'skucode': skuCode, 'quantity': quantity, 'price': str(price), 'show_price': context.showPrice, 'total': '{:.2f}'.format(total), 'price_per_item': '{:.2f}'.format(price_per_item), 'url': context.absolute_url(), 'supplier_name': supplier_name, 'supplier_email': supplier_email, 'vat_rate': vat_rate, 'vat_amount': str(self.calc_vat(vat_rate, total)), 'dimensions': dimensions, 'selectable_dimensions': context.getSelectableDimensions(), 'price_modifier': price_modifier } # item already in cart, update quantity else: item['quantity'] = item.get('quantity', 0) + quantity total = self.calc_item_total(price, item['quantity'], dimensions, price_modifier) item['dimensions'] = dimensions item['total'] = '{:.2f}'.format(total) item['price_per_item'] = '{:.2f}'.format(price_per_item) item['vat_amount'] = str(self.calc_vat(vat_rate, total)) # store cart in session cart_items[item_key] = item session[CART_KEY] = cart_items return True