Example #1
0
    def addtocart_ajax(self,
                       skuCode=None,
                       quantity=1,
                       var1choice=None,
                       var2choice=None):
        """ Add item to cart, return portlet HTML and translated status
        message
        """
        translate = self.context.translate

        success = self.cart._add_item(skuCode, quantity, var1choice,
                                      var2choice)
        if success:
            status_msg_label = _(u'msg_label_info', default=u"Information")
            status_msg_text = _(u'msg_item_added',
                                default=u"Added item to cart.")
        else:
            status_msg_label = _(u'msg_label_error', default=u"Error")
            status_msg_text = _(
                u'msg_item_disabled',
                default=u"Item is disabled and can't be added.")

        status_message = """\
<dt>%s</dt>
<dd>%s</dd>""" % (translate(status_msg_label), translate(status_msg_text))

        self.request.response.setHeader('Content-Type', 'application/json')
        return simplejson.dumps(
            dict(portlet_html=self.portlet_template(),
                 status_message=status_message))
Example #2
0
class DefaultStatusSet(object):
    implements(IStatusSet)
    adapts(Interface)
    # plone.registry.interfaces.IRecordsProxy
    # ftw.shop.interfaces.IShopConfiguration
    title = u"Default Status Set"

    vocabulary = SimpleVocabulary([
        SimpleTerm(
            value=1,
            token=1,
            title=_(u'status_online_pending',
                    default=u'Pending (online payment)'),
        ),
        SimpleTerm(
            value=2,
            token=2,
            title=_(u'status_confirmed',
                    default=u'Confirmed (online payment)'),
        ),
        SimpleTerm(
            value=3,
            token=3,
            title=_(u'status_on_account', default=u'On account'),
        )
    ])

    def __init__(self, context):
        self.context = context
        pass
Example #3
0
    def add_item(self,
                 skuCode=None,
                 quantity=1,
                 var1choice=None,
                 var2choice=None):
        """Add item to cart and redirect to referer.

        The item must be identified by either its skuCode if it is an item
        without variations, or by its variation key.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # Add item to cart
        success = self._add_item(skuCode, quantity, var1choice, var2choice)
        if success:
            ptool.addPortalMessage(
                _(u'msg_item_added', default=u'Added item to cart.'), 'info')
        else:
            ptool.addPortalMessage(
                _(u'msg_item_disabled',
                  default=u'Item is disabled and can\'t be added.'), 'error')

        # redirect to referer
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        if referer == 'localhost':
            referer = context.absolute_url()
        self.request.response.redirect(referer)
Example #4
0
class ICartPortlet(IPortletDataProvider):
    """A portlet that displays the shopping cart
    """
    mode = schema.Choice(title=_(u'Display mode'),
        description=_(u'Conditions under which portlet should be shown'),
        vocabulary=displayChoices,
        default='always'
        )
Example #5
0
class AddForm(base.AddForm):
    form_fields = form.Fields(ICartPortlet)
    label = _(u"label_add_cart_portlet",
              default=u"Add Shopping Cart Portlet")
    description = _(u"help_add_cart_portlet",
                default=u"This portlet displays the shopping cart contents.")

    def create(self, data):
        assignment = Assignment(**data)
        return assignment
Example #6
0
class DefaultPaymentProcessorChoiceStep(wizard.Step):
    implements(IPaymentProcessorChoiceStep)
    prefix = 'payment_processor_choice'
    label = _(u"label_default_payment_processor_choice_step",
              default="Payment Processor")
    title = _(u"title_default_payment_processor_step",
              default="Default Payment Processor Choice")
    description = _(u'help_default_payment_processor_choice_step', default=u"")
    fields = field.Fields(IDefaultPaymentProcessorChoice)
    fields['payment_processor'].widgetFactory = PaymentProcessorFieldWidget
Example #7
0
class DefaultOrderReviewStep(wizard.Step):
    implements(IOrderReviewStep)
    prefix = 'order-review'
    label = _(u'label_order_review_step', default="Order Review")
    title = _(u"title_default_order_review_step",
              default="Default Order Review Step")
    description = _(u'help_order_review_step', default=u'')
    index = zvptf.ViewPageTemplateFile('templates/checkout/order_review.pt')

    def __init__(self, context, request, wiz):
        super(wizard.Step, self).__init__(context, request)
        self.wizard = wiz
Example #8
0
    def update_cart(self):
        """Update cart contents.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # first delete items with quantity 0
        del_items = []
        # XXX - these are not skuCodes but item keys - rename!
        for skuCode in self.get_items().keys():
            try:
                qty = int(float(self.request.get('quantity_%s' % skuCode)))
                if qty == 0:
                    del_items.append(skuCode)
            except (ValueError, TypeError):
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return
        for skuCode in del_items:
            self._remove_item(skuCode)

        # now update quantities (and VAT amounts, done by update_item)
        for skuCode, item in self.get_items().items():
            quantity = float(self.request.get('quantity_%s' % skuCode))

            dimensions = self.request.get('dimension_%s' % skuCode, [])
            if not isinstance(dimensions, list):
                dimensions = [dimensions]
            if not validate_dimensions(dimensions,
                                       item['selectable_dimensions']):
                raise ValueError('Invalid dimensions.')
            dimensions = map(Decimal, dimensions)

            if quantity <= 0:
                raise ValueError('Invalid quantity.')

            self.update_item(skuCode, quantity, dimensions)

        ptool.addPortalMessage(
            _(u'msg_cart_updated', default=u"Cart updated."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #9
0
    def change_status(self):
        """Change status of several orders at once
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        order_storage = self.getOrderStorage()

        orders = self.request.form.get('orders', [])
        new_status = self.request.form.get('form.widgets.status', None)

        # Change status of the orders
        for order_id in orders:
            try:
                order_id = int(order_id)
            except ValueError:
                # Invalid order_id - continue with next one
                continue
            order = order_storage.getOrder(order_id)
            order.status = int(new_status)

        msg = _(u'msg_status_changed',
                default=u"Changed status for ${no_orders} orders.",
                mapping={ u"no_orders" : len(orders)})
        ptool.addPortalMessage(msg, 'info')
        return self.template()
Example #10
0
    def change_status(self):
        """Change status of several orders at once
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        order_storage = self.getOrderStorage()

        orders = self.request.form.get('orders', [])
        new_status = self.request.form.get('form.widgets.status', None)

        # Change status of the orders
        for order_id in orders:
            try:
                order_id = int(order_id)
            except ValueError:
                # Invalid order_id - continue with next one
                continue
            order = order_storage.getOrder(order_id)
            order.status = int(new_status)

        msg = _(u'msg_status_changed',
                default=u"Changed status for ${no_orders} orders.",
                mapping={ u"no_orders" : len(orders)})
        ptool.addPortalMessage(msg, 'info')
        return self.template()
Example #11
0
    def update_categories(self, categories):
        """Update the categories a ShopItem or ShopCategory belongs to
        """
        #categories = self.request.get('categories', None)
        old_uids = [obj.UID() for obj in self.context.listCategories()]

        # add the checked categories
        new_uids = [uid for uid in categories if uid not in old_uids]
        for c in new_uids:
            self.context.addToCategory(c)

        # remove the unchecked categories
        uids_delete = [uid for uid in old_uids if uid not in categories]
        categories_delete = uids_delete
        for c in categories_delete:
            self.context.removeFromCategory(c)

        #update ranks
        for c in self.context.listCategories():
            rank = self.context.REQUEST.get('rank_%s' % c.UID(), 1)
            self.context.setRankForCategory(c, rank)

        putils = getToolByName(self.context, 'plone_utils')
        putils.addPortalMessage(_(u'msg_categories_updated',
                                  default=u"Categories updated."), 'info')
        return self.context.REQUEST.RESPONSE.redirect('%s' %
                                            (self.context.absolute_url()))
Example #12
0
class IOrderReviewSchema(Interface):
    """Fields for the order review step.
    """

    comments = schema.Text(
            title=_(u'label_comments', default=u'Comments'),
            required=False)
Example #13
0
    def update_categories(self, categories):
        """Update the categories a ShopItem or ShopCategory belongs to
        """
        #categories = self.request.get('categories', None)
        old_uids = [obj.UID() for obj in self.context.listCategories()]

        # add the checked categories
        new_uids = [uid for uid in categories if uid not in old_uids]
        for c in new_uids:
            self.context.addToCategory(c)

        # remove the unchecked categories
        uids_delete = [uid for uid in old_uids if uid not in categories]
        categories_delete = uids_delete
        for c in categories_delete:
            self.context.removeFromCategory(c)

        #update ranks
        for c in self.context.listCategories():
            rank = self.context.REQUEST.get('rank_%s' % c.UID(), 1)
            self.context.setRankForCategory(c, rank)

        putils = getToolByName(self.context, 'plone_utils')
        putils.addPortalMessage(
            _(u'msg_categories_updated', default=u"Categories updated."),
            'info')
        return self.context.REQUEST.RESPONSE.redirect(
            '%s' % (self.context.absolute_url()))
Example #14
0
class IDefaultPaymentProcessorChoice(Interface):
    """Schema defining a customer choice from enabled payment processors
    """
    payment_processor = schema.Choice(
            title=_(u"label_payment_processor", default="Payment Processor"),
            vocabulary="ftw.shop.enabled_payment_processors",
            required=True)
Example #15
0
class IShippingAddress(Interface):
    """Schema defining a form for entering a shipping address
    """

    used = schema.Bool(
            title=_(u'label_used', default=u'Different from invoice address'),
            default=False,
            required=False)
Example #16
0
    def addtocart_ajax(self, skuCode=None, quantity=1,
                       var1choice=None, var2choice=None, dimensions=None):
        """ Add item to cart, return portlet HTML and translated status
        message
        """
        translate = self.context.translate

        # unpack dimensions from request
        dimensions = dimensions.split('|') if dimensions else []

        if validate_dimensions(dimensions, self.context.getSelectableDimensions()):
            dimensions = map(Decimal, dimensions)

            success = self.cart._add_item(skuCode, quantity, var1choice, var2choice, dimensions)

            if success:
                status_msg_label = _(u'msg_label_info', default=u"Information")
                status_msg_text = _(u'msg_item_added', default=u"Added item to cart.")
            else:
                status_msg_label = _(u'msg_label_error', default=u"Error")
                status_msg_text = _(u'msg_item_disabled', default=u"Item is disabled and can't be added.")

        else:
            status_msg_label = _(u'msg_label_error', default=u"Error")
            status_msg_text = _(u'msg_invalid_dimensions', default=u"Invalid dimensions.")

        status_message = """\
<dt>%s</dt>
<dd>%s</dd>""" % (translate(status_msg_label),
               translate(status_msg_text))

        self.request.response.setHeader('Content-Type', 'application/json')
        return simplejson.dumps(dict(portlet_html=self.portlet_template(),
                    status_message=status_message))
Example #17
0
    def purge_cart(self):
        """Remove all items from cart.
        """
        session = self.request.SESSION
        session[CART_KEY] = {}

        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        ptool.addPortalMessage(
            _(u'msg_cart_emptied', default=u"Cart emptied."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #18
0
    def purge_cart(self):
        """Remove all items from cart.
        """
        session = self.request.SESSION
        session[CART_KEY] = {}

        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        ptool.addPortalMessage(_(u'msg_cart_emptied',
                                 default=u"Cart emptied."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #19
0
class DefaultShippingAddressStep(wizard.Step):
    implements(IShippingAddressStep)
    prefix = 'shipping_address'
    label = _(u"label_default_shipping_address_step",
              default="Shipping Address")
    title = _(u"title_default_shipping_address_step",
              default="Default Shipping Address")
    description = _(u'help_default_shipping_address_step', default=u"")
    prefill_fields = [
        'title', 'firstname', 'lastname', 'company', 'street1', 'street2',
        'zipcode', 'city'
    ]
    fields = field.Fields(IShippingAddress) + \
    field.Fields(IDefaultContactInformation).select(
        'title',
        'firstname',
        'lastname',
        'company',
        'street1',
        'street2',
        'zipcode',
        'city')

    def __init__(self, context, request, wiz):
        super(wizard.Step, self).__init__(context, request)
        self.wizard = wiz

    def updateWidgets(self):
        super(DefaultShippingAddressStep, self).updateWidgets()
        if 'contact_information' in self.wizard.session and \
            (not 'shipping_address' in self.wizard.session \
            or self.wizard.session['shipping_address'] == {}):
            # Prefill shipping address with data from contact_info (prev step)
            contact_info = self.wizard.session['contact_information']
            for fieldname in self.prefill_fields:
                try:
                    self.widgets[fieldname].value = contact_info[fieldname]
                except KeyError:
                    pass
Example #20
0
    def addtocart_ajax(self, skuCode=None, quantity=1,
                       var1choice=None, var2choice=None):
        """ Add item to cart, return portlet HTML and translated status
        message
        """
        translate = self.context.translate

        success = self.cart._add_item(skuCode, quantity, var1choice, var2choice)
        if success:
            status_msg_label = _(u'msg_label_info', default=u"Information")
            status_msg_text = _(u'msg_item_added', default=u"Added item to cart.")
        else:
            status_msg_label = _(u'msg_label_error', default=u"Error")
            status_msg_text = _(u'msg_item_disabled', default=u"Item is disabled and can't be added.")

        status_message = """\
<dt>%s</dt>
<dd>%s</dd>""" % (translate(status_msg_label),
               translate(status_msg_text))

        self.request.response.setHeader('Content-Type', 'application/json')
        return simplejson.dumps(dict(portlet_html=self.portlet_template(),
                    status_message=status_message))
Example #21
0
    def update_cart(self):
        """Update cart contents.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # first delete items with quantity 0
        del_items = []
        # XXX - these are not skuCodes but item keys - rename!
        for skuCode in self.get_items().keys():
            try:
                qty = int(float(self.request.get('quantity_%s' % skuCode)))
                if qty == 0:
                    del_items.append(skuCode)
            except (ValueError, TypeError):
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return
        for skuCode in del_items:
            self._remove_item(skuCode)

        # now update quantities (and VAT amounts, done by update_item)
        for skuCode, item in self.get_items().items():
            quantity = int(float(self.request.get('quantity_%s' % skuCode)))
            if quantity != item['quantity'] and quantity != 0:
                self.update_item(skuCode, quantity)

        ptool.addPortalMessage(
            _(u'msg_cart_updated', default=u"Cart updated."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #22
0
    def update_cart(self):
        """Update cart contents.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # first delete items with quantity 0
        del_items = []
        # XXX - these are not skuCodes but item keys - rename!
        for skuCode in self.get_items().keys():
            try:
                qty = int(float(self.request.get('quantity_%s' % skuCode)))
                if qty == 0:
                    del_items.append(skuCode)
            except (ValueError, TypeError):
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return
        for skuCode in del_items:
            self._remove_item(skuCode)

        # now update quantities (and VAT amounts, done by update_item)
        for skuCode, item in self.get_items().items():
            quantity = int(float(self.request.get('quantity_%s' % skuCode)))
            if quantity != item['quantity'] and quantity != 0:
                self.update_item(skuCode, quantity)

        ptool.addPortalMessage(_(u'msg_cart_updated',
                                 default=u"Cart updated."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #23
0
    def add_item(self, skuCode=None, quantity=1,
                 var1choice=None, var2choice=None):
        """Add item to cart and redirect to referer.

        The item must be identified by either its skuCode if it is an item
        without variations, or by its variation key.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # Add item to cart
        success = self._add_item(skuCode, quantity, var1choice, var2choice)
        if success:
            ptool.addPortalMessage(_(u'msg_item_added',
                                     default=u'Added item to cart.'), 'info')
        else:
            ptool.addPortalMessage(_(u'msg_item_disabled',
                                     default=u'Item is disabled and can\'t be added.'), 'error')

        # redirect to referer
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        if referer == 'localhost':
            referer = context.absolute_url()
        self.request.response.redirect(referer)
Example #24
0
    def remove_item(self):
        """Remove an item from cart.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        # remove_item doesn't expect skuCode but item keys - rename!
        skuCode = self.request.get('skuCode')
        if skuCode:
            self._remove_item(skuCode)
            ptool.addPortalMessage(
                _(u'msg_cart_updated', default=u"Cart updated."), 'info')

        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #25
0
    def remove_item(self):
        """Remove an item from cart.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        # remove_item doesn't expect skuCode but item keys - rename!
        skuCode = self.request.get('skuCode')
        if skuCode:
            self._remove_item(skuCode)
            ptool.addPortalMessage(_(u'msg_cart_updated',
                                     default=u"Cart updated."), 'info')

        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
        return
Example #26
0
def SuppliersVocabulary(context):
    """Returns a vocabulary of the available suppliers
    """
    # context is the portal config options, whose context is the portal
    catalog = getToolByName(context, 'portal_catalog')
    suppliers = catalog(portal_type="Supplier")
    items = [(brain.UID, brain.Title) for brain in suppliers]
    terms = [SimpleTerm(value=pair[0],
                        token=pair[0],
                        title=pair[1]) for pair in items]
    terms.insert(0, SimpleTerm(value='',
                               token='none',
                               title=_("label_supplier_from_parent",
                                       default="Supplier from parent category")))

    directlyProvides(SuppliersVocabulary, IVocabularyFactory)
    return vocabulary.SimpleVocabulary(terms)
Example #27
0
    def __call__(self):
        """
        Self-submitting form that lets the user edit categories that
        ShopItems or ShopCategories belong to
        """
        form = self.request.form

        # Make sure we had a proper form submit, not just a GET request
        submitted = form.get('form.submitted', False)
        if submitted:
            edited_category_data = self.request.get('categories', [])
            self.update_categories(edited_category_data)
            IStatusMessage(self.request).addStatusMessage(_(
                u'msg_categories_updated', default=u"Categories updated."),
                                                          type="info")
            self.request.RESPONSE.redirect(self.context.absolute_url())

        return self.template()
Example #28
0
    def __call__(self):
        """
        Self-submitting form that lets the user edit categories that
        ShopItems or ShopCategories belong to
        """
        form = self.request.form

        # Make sure we had a proper form submit, not just a GET request
        submitted = form.get('form.submitted', False)
        if submitted:
            edited_category_data = self.request.get('categories', [])
            self.update_categories(edited_category_data)
            IStatusMessage(self.request).addStatusMessage(
                _(u'msg_categories_updated',
                  default=u"Categories updated."), type="info")
            self.request.RESPONSE.redirect(self.context.absolute_url())

        return self.template()
Example #29
0
class ShopConfigurationForm(RegistryEditForm, group.GroupForm):
    """Configuration form for the ftw.shop configlet
    """
    schema = IShopConfiguration
    fields = field.Fields(IShopConfiguration).omit(
        'shop_email', 'mail_bcc', 'mail_subject', 'always_notify_shop_owner',
        'payment_processor_step_group', 'enabled_payment_processors',
        'contact_info_step_group', 'shipping_address_step_group',
        'order_review_step_group', 'phone_number', 'vat_enabled', 'vat_number',
        'vat_rates')
    groups = (MailGroup, CheckoutGroup, VATGroup)
    label = _(u'label_shop_configuration', default=u"Shop configuration")

    def updateFields(self):
        super(ShopConfigurationForm, self).updateFields()

    def updateWidgets(self):
        super(ShopConfigurationForm, self).updateWidgets()
Example #30
0
    def cancel_orders(self):
        """Cancel orders by their order_ids
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        order_storage = self.getOrderStorage()

        orders = self.request.form.get('orders', [])
        for order_id in orders:
            try:
                order_id = int(order_id)
            except ValueError:
                # Invalid order_id - continue with next one
                continue
            order_storage.cancelOrder(order_id)
        msg = _(u'msg_order_cancelled',
                default=u"${no_orders} orders cancelled.",
                mapping={ u"no_orders" : len(orders)})
        ptool.addPortalMessage(msg, 'info')
        self.request.response.redirect("%s/order_manager" % context.absolute_url())
Example #31
0
def SuppliersVocabulary(context):
    """Returns a vocabulary of the available suppliers
    """
    # context is the portal config options, whose context is the portal
    catalog = getToolByName(context, 'portal_catalog')
    suppliers = catalog(portal_type="Supplier")
    items = [(brain.UID, brain.Title) for brain in suppliers]
    terms = [
        SimpleTerm(value=pair[0], token=pair[0], title=pair[1])
        for pair in items
    ]
    terms.insert(
        0,
        SimpleTerm(value='',
                   token='none',
                   title=_("label_supplier_from_parent",
                           default="Supplier from parent category")))

    directlyProvides(SuppliersVocabulary, IVocabularyFactory)
    return vocabulary.SimpleVocabulary(terms)
Example #32
0
    def cancel_orders(self):
        """Cancel orders by their order_ids
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')
        order_storage = self.getOrderStorage()

        orders = self.request.form.get('orders', [])
        for order_id in orders:
            try:
                order_id = int(order_id)
            except ValueError:
                # Invalid order_id - continue with next one
                continue
            order_storage.cancelOrder(order_id)
        msg = _(u'msg_order_cancelled',
                default=u"${no_orders} orders cancelled.",
                mapping={ u"no_orders" : len(orders)})
        ptool.addPortalMessage(msg, 'info')
        self.request.response.redirect("%s/order_manager" % context.absolute_url())
Example #33
0
    def addtocart_ajax(self,
                       skuCode=None,
                       quantity=1,
                       var1choice=None,
                       var2choice=None,
                       dimensions=None):
        """ Add item to cart, return portlet HTML and translated status
        message
        """
        translate = self.context.translate

        # unpack dimensions from request
        dimensions = dimensions.split('|') if dimensions else []

        if validate_dimensions(dimensions,
                               self.context.getSelectableDimensions()):
            dimensions = map(Decimal, dimensions)

            success = self.cart._add_item(skuCode, quantity, var1choice,
                                          var2choice, dimensions)

            if success:
                status_msg_label = _(u'msg_label_info', default=u"Information")
                status_msg_text = _(u'msg_item_added',
                                    default=u"Added item to cart.")
            else:
                status_msg_label = _(u'msg_label_error', default=u"Error")
                status_msg_text = _(
                    u'msg_item_disabled',
                    default=u"Item is disabled and can't be added.")

        else:
            status_msg_label = _(u'msg_label_error', default=u"Error")
            status_msg_text = _(u'msg_invalid_dimensions',
                                default=u"Invalid dimensions.")

        status_message = """\
<dt>%s</dt>
<dd>%s</dd>""" % (translate(status_msg_label), translate(status_msg_text))

        self.request.response.setHeader('Content-Type', 'application/json')
        return simplejson.dumps(
            dict(portlet_html=self.portlet_template(),
                 status_message=status_message))
Example #34
0
    def __call__(self):
        portal_url = getToolByName(self.context, "portal_url")
        ptool = getToolByName(self.context, "plone_utils")

        portal = portal_url.getPortalObject()
        shop = getattr(portal, "shop", None)
        if not shop:
            portal.invokeFactory("Folder", "shop", title="Shop")
            shop = portal.shop

        # Add Shopping Cart portlet to Shop Root
        column = getUtility(IPortletManager, name=u"plone.rightcolumn", context=shop)
        manager = getMultiAdapter((shop, column), IPortletAssignmentMapping)
        if "ftw.shop.portlets.cart" not in manager.keys():
            manager["ftw.shop.portlets.cart"] = portlets.cart.Assignment()

        ptool.addPortalMessage(_(u"msg_shop_initialized", default=u"Shop structure initialized."), "info")
        # redirect to referer
        referer = self.request.get("HTTP_REFERER", portal.absolute_url())
        if not referer in ["", "localhost"]:
            self.request.response.redirect(referer)
        else:
            self.request.response.redirect(portal.absolute_url())
        return
Example #35
0
    def add_level(self):
        fields = ['active', 'skuCode', 'price', 'description']
        request = getRequest()
        pps = getMultiAdapter((self.context, request), name='plone_portal_state')
        language = pps.language()
        if len(self.getVariationAttributes()) == 1:
            new_value_1 = translate(_('label_new_value_1', default=u'New value 1'), domain='ftw.shop', context=self.context, target_language=language)
            new_value_2 = translate(_('label_new_value_2', default=u'New value 2'), domain='ftw.shop', context=self.context, target_language=language)
            new_attr = translate(_('label_new_attr', default=u'New attribute'), domain='ftw.shop', context=self.context, target_language=language)
            self.context.getField('variation2_values').set(self.context, [new_value_1, new_value_2])
            self.context.getField('variation2_attribute').set(self.context, new_attr)

            # Initialize var data for newly added level with default values
            for i in range(len(self.getVariation1Values())):
                for j in range(len(self.getVariation2Values())):
                    vardata = {}
                    for f in fields:
                        vcode = "var-%s-%s" % (i, j)
                        data = self.getVariationData(i, j, f)
                        vardata[f] = data
                        partial_vardict = {vcode: vardata}
                        self.updateVariationConfig(partial_vardict)

        elif len(self.getVariationAttributes()) == 0:
            new_value_1 = translate(_('label_new_value_1', default=u'New value 1'), domain='ftw.shop', context=self.context, target_language=language)
            new_value_2 = translate(_('label_new_value_2', default=u'New value 2'), domain='ftw.shop', context=self.context, target_language=language)
            new_attr = translate(_('label_new_attr', default=u'New attribute'), domain='ftw.shop', context=self.context, target_language=language)

            self.context.getField('variation1_values').set(self.context, [new_value_1, new_value_2])
            self.context.getField('variation1_attribute').set(self.context, new_attr)

            # Initialize var data for newly added level with default values
            for i in range(len(self.getVariation1Values())):
                vardata = {}
                for f in fields:
                    vcode = "var-%s" % (i)
                    data = self.getVariationData(i, None, f)
                    vardata[f] = data
                    partial_vardict = {vcode: vardata}
                    self.updateVariationConfig(partial_vardict)
Example #36
0
from ftw.shop import shopMessageFactory as _
from ftw.shop.interfaces import IShopCategory
from ftw.shop.config import PROJECTNAME
from ftw.shop.content.categorizeable import Categorizeable


ShopCategorySchema = ATFolderSchema.copy() + atapi.Schema((
        atapi.ReferenceField(
            'supplier',
            required = 0,
            languageIndependent=True,
            relationship = 'item_supplier',
            vocabulary_factory="ftw.shop.suppliers_vocabulary",
            widget = atapi.ReferenceWidget(
                label = _(u"label_supplier", default=u"Supplier"),
                description = _(u"desc_supplier", default=u""),
                checkbox_bound = 10,
                ),
            ),
        ))


class ShopCategory(Categorizeable, ATFolder):
    """A category for shop items"""
    implements(IShopCategory)

    meta_type = "ShopCategory"
    schema = ShopCategorySchema

    def fullTitle(self):
Example #37
0
 def validate(self, value):
     super(EmailAddressValidator, self).validate(value)
     if not value or not is_email_valid(value):
         raise Invalid(_(u'This email address is invalid.'))
Example #38
0
class DefaultContactInfoStep(wizard.Step):
    implements(IContactInformationStep)
    prefix = 'contact_information'
    label = _(u"label_default_contact_info_step",
              default="Contact Information")
    title = _(u"title_default_contact_info_step",
              default="Default Contact Information")
    description = _(u'help_default_contact_info_step', default=u"")
    fields = field.Fields(IDefaultContactInformation)

    prefill_fields = [
        'title', 'firstname', 'lastname', 'email', 'company', 'street1',
        'street2', 'phone', 'zipcode', 'city', 'country'
    ]

    def __init__(self, context, request, wiz):
        super(wizard.Step, self).__init__(context, request)
        self.wizard = wiz

    def updateWidgets(self):
        super(DefaultContactInfoStep, self).updateWidgets()
        request = self.context.REQUEST

        # if user is authenticated:
        # prefill form from portal_memberdata
        mt = getToolByName(self.context, 'portal_membership')
        if not mt.isAnonymousUser():
            member = mt.getAuthenticatedMember()
            fullname = member.getProperty('fullname', '')

            if not isinstance(fullname, unicode):
                # assume it's uft-8
                fullname = fullname.decode('utf-8')

            if fullname.find(' ') > -1:
                firstname, lastname = fullname.rsplit(' ', 1)
            else:
                firstname = lastname = ''
            email = member.getProperty('email')

            self.widgets['firstname'].value = firstname
            self.widgets['lastname'].value = lastname
            self.widgets['email'].value = unicode(email)

        if COOKIE_ADDRESS_KEY in request:
            # Prefill contact data with values from cookie
            cookie_data = simplejson.loads(
                base64.b64decode(request[COOKIE_ADDRESS_KEY]))
            for key in cookie_data.keys():
                if isinstance(cookie_data[key], basestring):
                    cookie_data[key] = unicode(cookie_data[key])

            for fieldname in self.prefill_fields:
                try:
                    self.widgets[fieldname].value = cookie_data[fieldname]
                except KeyError:
                    pass

        elif SESSION_ADDRESS_KEY in request.SESSION.keys():
            # Prefill contact data form with values from session
            contact_info = request.SESSION[SESSION_ADDRESS_KEY]
            for fieldname in self.prefill_fields:
                try:
                    self.widgets[fieldname].value = contact_info[fieldname]
                except KeyError:
                    pass

        self.widgets['zipcode'].size = 5
Example #39
0
 def title(self):
     """This property is used to give the title of the portlet in the
     "manage portlets" screen.
     """
     return _(u"label_cart_portlet", default=u"Cart Portlet")
Example #40
0
from ftw.shop import shopMessageFactory as _
from ftw.shop.interfaces import IShopItem
from plone.app.portlets.portlets import base
from plone.portlets.interfaces import IPortletDataProvider
from zope import schema
from zope.component import getMultiAdapter
from zope.formlib import form
from zope.interface import implements
from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary


displayChoices = SimpleVocabulary(
    [SimpleTerm(value='always',
                token='always',
                title=_(u'label_always',
                        default=u'Always'),
                ),
     SimpleTerm(value='only_if_items',
                token='only_if_items',
                title=_(u'label_only_if_items',
                        default=u'Only if ShopItems available in current folder'),
                )
      ]
    )


class ICartPortlet(IPortletDataProvider):
    """A portlet that displays the shopping cart
    """
    mode = schema.Choice(title=_(u'Display mode'),
        description=_(u'Conditions under which portlet should be shown'),
Example #41
0
class CheckoutWizard(wizard.Wizard):
    label = _(u"label_checkout_wizard", default="Checkout")
    index = zvptf.ViewPageTemplateFile('templates/checkout-wizard.pt')

    def __init__(self, context, request):
        super(CheckoutWizard, self).__init__(context, request)
        self.context = context
        self.request = request

    def getSelectedPaymentProcessor(self):
        payment_processor = None
        if 'payment_processor_choice' not in self.session.keys():
            return None
        try:
            pp_name = self.session.get('payment_processor_choice').get(
                'payment_processor')
        except KeyError:
            try:
                pp_name = self.request.SESSION.get(
                    'payment_processor_choice').get('payment_processor')
            except KeyError:
                # No payment processor step activated
                pp_name = "none"
        for name, adapter in getAdapters(
            (self.context, self.request, self.context), IPaymentProcessor):
            if name == pp_name:
                payment_processor = adapter
        return payment_processor

    @property
    def steps(self):
        contact_info_steps = ()
        shipping_address_steps = ()
        contact_info_step_groups = getAdapters(
            (self.context, self.request, self), IContactInformationStepGroup)
        shipping_address_step_groups = getAdapters(
            (self.context, self.request, self), IShippingAddressStepGroup)
        payment_processor_step_groups = getAdapters(
            (self.context, self.request, self), IPaymentProcessorStepGroup)
        order_review_step_groups = getAdapters(
            (self.context, self.request, self), IOrderReviewStepGroup)
        registry = getUtility(IRegistry)
        shop_config = registry.forInterface(IShopConfiguration)

        # Get steps for selected Contact Info Step Group
        selected_contact_info_step_group = shop_config.contact_info_step_group
        for name, step_group_adapter in contact_info_step_groups:
            if name == selected_contact_info_step_group:
                contact_info_steps = step_group_adapter.steps

        # Get steps for selected Shipping Address Step Group
        selected_shipping_address_step_group = shop_config.shipping_address_step_group
        for name, step_group_adapter in shipping_address_step_groups:
            if name == selected_shipping_address_step_group:
                shipping_address_steps = step_group_adapter.steps

        # Get steps for selected Payment Processor Step Group
        selected_pp_step_group = shop_config.payment_processor_step_group
        for name, step_group_adapter in payment_processor_step_groups:
            if name == selected_pp_step_group:
                payment_processor_steps = step_group_adapter.steps

        # Get steps for selected Order Review Step Group
        selected_order_review_step_group = shop_config.order_review_step_group
        for name, step_group_adapter in order_review_step_groups:
            if name == selected_order_review_step_group:
                order_review_steps = step_group_adapter.steps

        return contact_info_steps + \
               shipping_address_steps + \
               payment_processor_steps + \
               order_review_steps

    @button.buttonAndHandler(_(u'btn_back', default="Back"),
                             name='back',
                             condition=lambda form: not form.onFirstStep)
    def handleBack(self, action):
        data, errors = self.currentStep.extractData()
        if errors:
            errorMessage = '<ul>'
            for error in errors:
                if errorMessage.find(error.message):
                    errorMessage += '<li>' + error.message + '</li>'
            errorMessage += '</ul>'
            self.status = errorMessage

        else:
            self.currentStep.applyChanges(data)
            self.updateCurrentStep(self.currentIndex - 1)

            # Back can change the conditions for the finish button,
            # so we need to reconstruct the button actions, since we
            # do not redirect.
            self.updateActions()

    @button.buttonAndHandler(_(u'btn_continue', default='Next'),
                             name='continue',
                             condition=lambda form: not form.onLastStep)
    def handleContinue(self, action):
        data, errors = self.currentStep.extractData()
        if errors:
            errorMessage = '<ul>'
            for error in errors:
                if errorMessage.find(error.message):
                    errorMessage += '<li>' + error.message + '</li>'
            errorMessage += '</ul>'
            self.status = errorMessage
        else:

            self.currentStep.applyChanges(data)
            self.updateCurrentStep(self.currentIndex + 1)

            # Proceed can change the conditions for the finish button,
            # so we need to reconstruct the button actions, since we
            # do not redirect.
            self.updateActions()

    @button.buttonAndHandler(
        _(u'btn_finish', default='Finish'),
        name='finish',
        condition=lambda form: form.allStepsFinished or form.onLastStep)
    def handleFinish(self, action):
        data, errors = self.currentStep.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        else:
            self.status = self.successMessage
            self.finished = True
        self.currentStep.applyChanges(data)
        self.finish()

        address_data = {}
        address_data.update(self.session['contact_information'])
        self.request.SESSION[SESSION_ADDRESS_KEY] = address_data

        shipping_data = {}
        shipping_data.update(self.session['shipping_address'])
        self.request.SESSION[SESSION_SHIPPING_KEY] = shipping_data

        self.request.SESSION['order_confirmation'] = True

        payment_processor_choice = {}
        if 'payment_processor_choice' in self.session.keys():
            payment_processor_choice.update(
                self.session['payment_processor_choice'])
        self.request.SESSION[
            'payment_processor_choice'] = payment_processor_choice

        # Save contact information in a cookie in order to prefill
        # form if customer returns
        cookie_value = base64.b64encode(
            simplejson.dumps(self.session['contact_information']))
        expiry_date = (
            datetime.now() +
            timedelta(days=90)).strftime("%a, %d-%b-%Y %H:%M:%S GMT")
        self.request.RESPONSE.setCookie(COOKIE_ADDRESS_KEY,
                                        cookie_value,
                                        path='/',
                                        expires=expiry_date)

        self.request.SESSION[self.sessionKey] = {}
        self.sync()

        pp = self.getSelectedPaymentProcessor()
        if pp is not None and pp.external:
            self.request.SESSION['external-processor-url'] = pp.url
            self.request.SESSION[
                'external-processor-url'] = "http://localhost:8077/"

        self.request.response.redirect('checkout')
Example #42
0
    from Products.Archetypes.atapi import registerType

from ftw.shop.interfaces import IShopItem, IBuyable
from ftw.shop.content.categorizeable import Categorizeable
from ftw.shop.config import PROJECTNAME
from ftw.shop import shopMessageFactory as _


ShopItemSchema = ATContentTypeSchema.copy() + atapi.Schema((

        atapi.ImageField(
            'image',
            required=False,
            languageIndependent=True,
            widget = atapi.ImageWidget(
                label = _(u"label_image", default=u"Image"),
            ),
            storage=AnnotationStorage(),
                sizes= {'large': (768, 768),
                         'mini': (200, 200),
                         'thumb': (128, 128),
                  },
            ),


        atapi.TextField(
            'text',
            required=False,
            searchable=True,
            primary=True,
            storage=atapi.AnnotationStorage(migrate=True),
Example #43
0
    def download_csv(self):
        """Returns a CSV file containing the shop orders
        """

        filename = "orders.csv"
        stream = cStringIO.StringIO()
        csv_writer = csv.writer(stream, dialect='excel', delimiter=';',
                                quotechar='"', quoting=csv.QUOTE_MINIMAL)
        core_cols = ['order_id',
                      'title',
                      'status',
                      'total',
                      'date',
                      'customer_title',
                      'customer_firstname',
                      'customer_lastname',
                      'customer_company',
                      'customer_email',
                      'customer_street1',
                      'customer_street2',
                      'customer_phone',
                      'customer_zipcode',
                      'customer_city',
                      'customer_shipping_address',
                      'customer_country',
                      'customer_comments']

        # Create union of core_cols + all_cols to retain order
        all_cols = self.order_storage.getFieldNames()
        columns = core_cols + filter(lambda x:x not in core_cols, all_cols)
        cart_cols = ['sku_code', 'quantity', 'dimensions', 'title', 'price',
                     'item_total', 'supplier_name', 'supplier_email']

        column_titles = [COLUMN_TITLES[col].decode('utf-8').encode('cp1252') for col in columns + cart_cols]
        # Write header row
        csv_writer.writerow(column_titles)

        for order in self.order_results:
            order_data = [getattr(order, attr, '') for attr in columns]

            # Get the total via getTotal accessor to convert it to Decimal
            order_data[columns.index('total')] = order.getTotal()

            for i, value in enumerate(order_data):
                if isinstance(value, unicode):
                    order_data[i] = value.encode('cp1252')

            for cart_item in order.cartitems:
                # format dimensions
                dimensions = [(cart_item.dimensions[i], dim) for i, dim in enumerate(cart_item.selectable_dimensions)]
                dim_strings = [' '.join([str(dim[0]), translate(_(dim[1]), context=self.request)]) for dim in dimensions]
                dim_formatted = ','.join(dim_strings)

                cart_data = [cart_item.sku_code,
                            cart_item.quantity,
                            dim_formatted,
                            cart_item.title,
                            cart_item.getPrice(),
                            cart_item.getTotal(),
                            cart_item.supplier_name,
                            cart_item.supplier_email]

                for i, value in enumerate(cart_data):
                    if isinstance(value, unicode):
                        cart_data[i] = value.encode('cp1252')

                csv_writer.writerow(order_data + cart_data)

        RESPONSE = self.request.RESPONSE
        header_value = contentDispositionHeader('attachment',
                                                'cp1252',
                                                filename=filename)
        if not DEBUG:
            RESPONSE.setHeader("Content-Disposition", header_value)
            RESPONSE.setHeader("Content-Type",
                           'text/comma-separated-values;charset=%s' % 'cp1252')
        else:
            RESPONSE.setHeader("Content-Type",
                           'text/plain; charset=%s' % 'cp1252')

        stream.seek(0)
        return stream.read()
Example #44
0
class DefaultShippingAddressStepGroup(BaseStepGroup):
    implements(IShippingAddressStepGroup)
    adapts(Interface, Interface, Interface)
    title = _(u"title_default_shipping_address_step_group",
              default="Default Shipping Address")
    steps = (DefaultShippingAddressStep, )
Example #45
0
class VATGroup(group.Group):
    label = _('label_vat_group', default=u'VAT')
    fields = field.Fields(IShopConfiguration).select('vat_enabled',
                                                     'vat_number', 'vat_rates')
Example #46
0
    def checkout(self):
        """Process checkout
        """
        context = aq_inner(self.context)
        session = context.REQUEST.SESSION
        ptool = getToolByName(context, 'plone_utils')
        url = context.absolute_url()

        # check if we have something in the cart
        items = self.cart_items()
        if not items:
            ptool.addPortalMessage(_(u'msg_no_cart',
                            default=u"Can't proceed with empty cart."),
                'error')
            self.request.response.redirect(url)
        navroot = api.portal.get_navigation_root(context)
        omanager = getMultiAdapter((navroot, self.request),
                                   name=u'order_manager')


        # Check we got all the data we need from the wizard
        try:
            order_id = omanager.addOrder()
        except MissingCustomerInformation:
            self.request.response.redirect('%s/checkout-wizard' % url)
            return
        except MissingShippingAddress:
            self.request.response.redirect('%s/checkout-wizard' % url)
            return
        except MissingOrderConfirmation:
            self.request.response.redirect('%s/checkout-wizard' % url)
            return
        except MissingPaymentProcessor:
            self.request.response.redirect('%s/checkout-wizard' % url)
            return

        # Get the payment processor selected by the customer
        payment_processor_name = session.get(
            'payment_processor_choice').get('payment_processor')
        for name, adapter in getAdapters((context, context.REQUEST, context),
                                         IPaymentProcessor):
            if name == payment_processor_name:
                payment_processor = adapter

        if not payment_processor_name or not payment_processor.external:
            # No payment processor step at all OR payment by invoice

            customer_info = self.request.SESSION[SESSION_ADDRESS_KEY]
            self.request.SESSION.invalidate()

            # Get a new session object, since the old one still returns
            # stale data even though it has been invalidated
            session = context.session_data_manager.getSessionData()
            session[SESSION_ADDRESS_KEY] = customer_info

            # Set correct status for payment by invoice
            order = omanager.getOrder(order_id)
            order.status = ONACCOUNT_KEY

            omanager.sendOrderMails(order_id)

            self.request.response.redirect(
                        '%s/thankyou?order_id=%s' % (url, order.title))
            return
        else:
            #self.request.SESSION.invalidate()
            self.request.SESSION['order_id'] = order_id
            pp_launch_page = 'external-payment-processor'
            pp_launch_page = payment_processor.launch_page
            self.request.response.redirect('%s/%s' % (url, pp_launch_page))
            return
Example #47
0
from zope.interface import implements


from Products.ATContentTypes.config import HAS_LINGUA_PLONE
if HAS_LINGUA_PLONE:
    from Products.LinguaPlone.public import registerType
else:
    from Products.Archetypes.atapi import registerType


SupplierSchema = ATContentTypeSchema.copy() + atapi.Schema((

        atapi.TextField(
            name='email',
            required=True,
            label=_(u'label_supplier_email', default=u"E-Mail")),

        atapi.TextField(
            name='address',
            required=False,
            allowable_content_types=('text/plain', ),
            default_content_type='text/plain',
            default_input_type='text/plain',
            default_output_type='text/x-html-safe',

            widget=atapi.RichWidget(
                label=_(u'label_supplier_address', default=u"Address"),
                description=_(u'help_supplier_address',
                              default=u"Supplier's postal address")))))

Example #48
0
if HAS_LINGUA_PLONE:
    from Products.LinguaPlone.public import registerType
else:
    from Products.Archetypes.atapi import registerType

from ftw.shop.interfaces import IBuyable
from ftw.shop.interfaces import IShopItem
from ftw.shop.interfaces import IVariationConfig
from ftw.shop.content.categorizeable import Categorizeable
from ftw.shop.config import PROJECTNAME
from ftw.shop import shopMessageFactory as _


selectable_dimensions = {
    'no_dimensions': {
        'label': _(u"label_no_dimensions", default=u"---"),
        'dimension_unit': None,
        'dimensions': []
    },
    'length_mm_mm': {
        'label': _(u"label_length", default=u"Length"),
        'dimension_unit': u'mm',
        'dimensions': [_(u"Length (mm)")]
    },
    'length_m_m': {
        'label': _(u"label_length", default=u"Length"),
        'dimension_unit': u'm',
        'dimensions': [_(u"Length (m)")]
    },
    'length_width_mm_mm2': {
        'label': _(u"label_l_w", default=u"Length, Width"),
Example #49
0
class MailGroup(group.Group):
    label = _('label_mail_group', default=u'Mail')
    fields = field.Fields(IShopConfiguration).select(
        'shop_email', 'mail_bcc', 'mail_subject', 'always_notify_shop_owner')
Example #50
0
class DefaultOrderReviewStepGroup(BaseStepGroup):
    implements(IOrderReviewStepGroup)
    adapts(Interface, Interface, Interface)
    title = _(u"title_default_order_review_step_group",
              default="Default Order Review Step Group")
    steps = (DefaultOrderReviewStep, )
Example #51
0
class CheckoutGroup(group.Group):
    label = _('label_checkout_group', default=u'Checkout')
    fields = field.Fields(IShopConfiguration).select(
        'payment_processor_step_group', 'enabled_payment_processors',
        'contact_info_step_group', 'shipping_address_step_group',
        'order_review_step_group', 'phone_number')
Example #52
0
    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()
Example #53
0
    def update_cart(self):
        """Update cart contents.
        """
        context = aq_inner(self.context)
        ptool = getToolByName(context, 'plone_utils')

        # delete items with quantity 0
        del_items = []
        for item_key in self.get_items().keys():
            try:
                qty = int(float(self.request.get('quantity_%s' % item_key)))
                if qty <= 0:
                    del_items.append(item_key)
            except (ValueError, TypeError):
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return
        for item_key in del_items:
            self._remove_item(item_key)

        # now update quantities and dimensions
        for item_key, item in self.get_items().items():
            quantity = float(self.request.get('quantity_%s' % item_key))

            dimensions = self.request.get('dimension_%s' % item_key, [])
            if not isinstance(dimensions, list):
                dimensions = [dimensions]

            if not validate_dimensions(dimensions, item['selectable_dimensions']):
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return

            dimensions = map(Decimal, dimensions)

            # check that dimension changes do not collide
            item = self.get_items()[item_key]
            new_key = self.get_item_key(
                item['uid'],
                item['variation_code'] if 'variation_code' in item else '',
                dimensions)
            if new_key != item_key and new_key in self.get_items().keys():
                ptool.addPortalMessage(
                    _(u'msg_cart_invalidvalue',
                      default=u"Invalid Values specified. Cart not updated."),
                    'error')
                referer = self.request.get('HTTP_REFERER',
                                           context.absolute_url())
                self.request.response.redirect(referer)
                return

            self.update_item(item_key, quantity, dimensions)

        ptool.addPortalMessage(_(u'msg_cart_updated',
                                 default=u"Cart updated."), 'info')
        referer = self.request.get('HTTP_REFERER', context.absolute_url())
        self.request.response.redirect(referer)
Example #54
0
class DefaultPaymentProcessorStepGroup(BaseStepGroup):
    implements(IPaymentProcessorStepGroup)
    adapts(Interface, Interface, Interface)
    title = _(u"title_default_payment_processor_step_group",
              default="Default Payment Processor Choice")
    steps = (DefaultPaymentProcessorChoiceStep, )