From ba1bb442d2aa1b7983784541979ff2f40919b0ca Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 12:38:32 +0100 Subject: [PATCH 01/27] New template style --- pcommerce/__init__.py | 6 - pcommerce/core/__init__.py | 26 - pcommerce/core/adapters.py | 150 ---- pcommerce/core/address.py | 108 --- pcommerce/core/browser/__init__.py | 0 pcommerce/core/browser/address.pt | 348 -------- pcommerce/core/browser/cart.pt | 131 --- pcommerce/core/browser/cart.py | 49 -- pcommerce/core/browser/checkout.pt | 72 -- pcommerce/core/browser/checkout.py | 376 --------- pcommerce/core/browser/components/__init__.py | 0 pcommerce/core/browser/components/address.pt | 17 - pcommerce/core/browser/components/address.py | 26 - pcommerce/core/browser/components/base.py | 273 ------- .../core/browser/components/configure.zcml | 61 -- .../core/browser/components/confirmation.pt | 63 -- .../core/browser/components/confirmation.py | 16 - pcommerce/core/browser/components/gtc.pt | 28 - pcommerce/core/browser/components/gtc.py | 27 - pcommerce/core/browser/components/overview.pt | 55 -- pcommerce/core/browser/components/overview.py | 16 - pcommerce/core/browser/components/payment.pt | 17 - pcommerce/core/browser/components/payment.py | 27 - pcommerce/core/browser/components/payments.pt | 38 - pcommerce/core/browser/components/payments.py | 29 - pcommerce/core/browser/components/shipment.pt | 26 - pcommerce/core/browser/components/shipment.py | 50 -- .../core/browser/components/shipments.pt | 89 -- .../core/browser/components/shipments.py | 63 -- pcommerce/core/browser/configlet.pt | 250 ------ pcommerce/core/browser/configlet.py | 92 --- pcommerce/core/browser/configure.zcml | 190 ----- pcommerce/core/browser/folder.pt | 51 -- pcommerce/core/browser/folder.py | 92 --- pcommerce/core/browser/getprice.js | 27 - pcommerce/core/browser/getprice.pt | 8 - pcommerce/core/browser/getprice.py | 40 - pcommerce/core/browser/images.pt | 132 --- pcommerce/core/browser/images.py | 52 -- pcommerce/core/browser/images/price_icon.gif | Bin 595 -> 0 bytes .../core/browser/images/product_icon.gif | Bin 1048 -> 0 bytes .../core/browser/images/variation_icon.gif | Bin 1048 -> 0 bytes .../core/browser/javascripts/as_customer.js | 17 - pcommerce/core/browser/macros.pt | 220 ----- pcommerce/core/browser/manage_orders.pt | 59 -- pcommerce/core/browser/order_details.pt | 53 -- pcommerce/core/browser/orders.py | 258 ------ pcommerce/core/browser/portlets/__init__.py | 0 pcommerce/core/browser/portlets/cart.pt | 30 - pcommerce/core/browser/portlets/cart.py | 52 -- .../core/browser/portlets/configure.zcml | 17 - pcommerce/core/browser/prices.pt | 149 ---- pcommerce/core/browser/prices.py | 58 -- pcommerce/core/browser/product.pt | 36 - pcommerce/core/browser/product.py | 155 ---- pcommerce/core/browser/variation.pt | 46 -- pcommerce/core/browser/variation.py | 8 - pcommerce/core/browser/variations.pt | 41 - pcommerce/core/browser/variations.py | 11 - pcommerce/core/browser/viewlets/__init__.py | 0 pcommerce/core/browser/viewlets/buy.pt | 22 - pcommerce/core/browser/viewlets/buy.py | 46 -- .../core/browser/viewlets/configure.zcml | 64 -- pcommerce/core/browser/viewlets/hot.pt | 10 - pcommerce/core/browser/viewlets/hot.py | 54 -- pcommerce/core/browser/viewlets/info.pt | 19 - pcommerce/core/browser/viewlets/info.py | 47 -- pcommerce/core/browser/viewlets/new.pt | 10 - pcommerce/core/browser/viewlets/new.py | 54 -- pcommerce/core/browser/viewlets/processor.py | 52 -- pcommerce/core/browser/viewlets/related.pt | 10 - pcommerce/core/browser/viewlets/related.py | 56 -- pcommerce/core/browser/viewlets/variation.pt | 10 - pcommerce/core/browser/viewlets/variation.py | 53 -- pcommerce/core/cart.py | 256 ------ pcommerce/core/charge.py | 17 - pcommerce/core/config.py | 46 -- pcommerce/core/configure.zcml | 70 -- pcommerce/core/content/__init__.py | 0 pcommerce/core/content/price.py | 42 - pcommerce/core/content/product.py | 136 --- pcommerce/core/content/variation.py | 62 -- pcommerce/core/currency.py | 74 -- pcommerce/core/data.py | 23 - pcommerce/core/events.py | 39 - pcommerce/core/interfaces.py | 488 ----------- .../core/locales/de/LC_MESSAGES/pcommerce.po | 770 ----------------- .../core/locales/de/LC_MESSAGES/plone.po | 54 -- .../core/locales/es/LC_MESSAGES/pcommerce.po | 771 ------------------ .../core/locales/es/LC_MESSAGES/plone.po | 56 -- .../core/locales/fr/LC_MESSAGES/pcommerce.po | 760 ----------------- .../core/locales/fr/LC_MESSAGES/plone.po | 55 -- .../core/locales/nl/LC_MESSAGES/pcommerce.po | 754 ----------------- .../core/locales/nl/LC_MESSAGES/plone.po | 52 -- .../core/locales/no/LC_MESSAGES/pcommerce.po | 752 ----------------- .../core/locales/no/LC_MESSAGES/plone.po | 56 -- pcommerce/core/locales/pcommerce.pot | 690 ---------------- pcommerce/core/locales/plone.pot | 51 -- pcommerce/core/order.py | 569 ------------- pcommerce/core/permissions.zcml | 39 - pcommerce/core/plone3.py | 2 - pcommerce/core/processor.py | 35 - pcommerce/core/profiles/default/actions.xml | 18 - pcommerce/core/profiles/default/catalog.xml | 15 - .../core/profiles/default/controlpanel.xml | 19 - .../core/profiles/default/cssregistry.xml | 6 - .../core/profiles/default/factorytool.xml | 9 - .../core/profiles/default/jsregistry.xml | 10 - pcommerce/core/profiles/default/metadata.xml | 7 - .../pcommerce.core_migrate05a105a2.txt | 0 pcommerce/core/profiles/default/portlets.xml | 10 - .../core/profiles/default/propertiestool.xml | 19 - pcommerce/core/profiles/default/rolemap.xml | 35 - pcommerce/core/profiles/default/skins.xml | 8 - pcommerce/core/profiles/default/types.xml | 10 - .../core/profiles/default/types/Folder.xml | 9 - .../core/profiles/default/types/Price.xml | 27 - .../core/profiles/default/types/Product.xml | 44 - .../core/profiles/default/types/Variation.xml | 43 - pcommerce/core/profiles/default/viewlets.xml | 20 - pcommerce/core/registry.py | 28 - pcommerce/core/required.py | 9 - pcommerce/core/setuphandlers.py | 19 - .../core/skins/pcommerce/pcommerce.css.dtml | 530 ------------ pcommerce/core/steps.py | 16 - pcommerce/core/vocabulary.py | 27 - setup.py | 3 +- 127 files changed, 2 insertions(+), 12496 deletions(-) delete mode 100644 pcommerce/__init__.py delete mode 100644 pcommerce/core/__init__.py delete mode 100644 pcommerce/core/adapters.py delete mode 100644 pcommerce/core/address.py delete mode 100644 pcommerce/core/browser/__init__.py delete mode 100644 pcommerce/core/browser/address.pt delete mode 100644 pcommerce/core/browser/cart.pt delete mode 100644 pcommerce/core/browser/cart.py delete mode 100644 pcommerce/core/browser/checkout.pt delete mode 100644 pcommerce/core/browser/checkout.py delete mode 100644 pcommerce/core/browser/components/__init__.py delete mode 100644 pcommerce/core/browser/components/address.pt delete mode 100644 pcommerce/core/browser/components/address.py delete mode 100644 pcommerce/core/browser/components/base.py delete mode 100644 pcommerce/core/browser/components/configure.zcml delete mode 100644 pcommerce/core/browser/components/confirmation.pt delete mode 100644 pcommerce/core/browser/components/confirmation.py delete mode 100644 pcommerce/core/browser/components/gtc.pt delete mode 100644 pcommerce/core/browser/components/gtc.py delete mode 100644 pcommerce/core/browser/components/overview.pt delete mode 100644 pcommerce/core/browser/components/overview.py delete mode 100644 pcommerce/core/browser/components/payment.pt delete mode 100644 pcommerce/core/browser/components/payment.py delete mode 100644 pcommerce/core/browser/components/payments.pt delete mode 100644 pcommerce/core/browser/components/payments.py delete mode 100644 pcommerce/core/browser/components/shipment.pt delete mode 100644 pcommerce/core/browser/components/shipment.py delete mode 100644 pcommerce/core/browser/components/shipments.pt delete mode 100644 pcommerce/core/browser/components/shipments.py delete mode 100644 pcommerce/core/browser/configlet.pt delete mode 100644 pcommerce/core/browser/configlet.py delete mode 100644 pcommerce/core/browser/configure.zcml delete mode 100644 pcommerce/core/browser/folder.pt delete mode 100644 pcommerce/core/browser/folder.py delete mode 100644 pcommerce/core/browser/getprice.js delete mode 100644 pcommerce/core/browser/getprice.pt delete mode 100644 pcommerce/core/browser/getprice.py delete mode 100644 pcommerce/core/browser/images.pt delete mode 100644 pcommerce/core/browser/images.py delete mode 100644 pcommerce/core/browser/images/price_icon.gif delete mode 100644 pcommerce/core/browser/images/product_icon.gif delete mode 100644 pcommerce/core/browser/images/variation_icon.gif delete mode 100644 pcommerce/core/browser/javascripts/as_customer.js delete mode 100644 pcommerce/core/browser/macros.pt delete mode 100644 pcommerce/core/browser/manage_orders.pt delete mode 100644 pcommerce/core/browser/order_details.pt delete mode 100644 pcommerce/core/browser/orders.py delete mode 100644 pcommerce/core/browser/portlets/__init__.py delete mode 100644 pcommerce/core/browser/portlets/cart.pt delete mode 100644 pcommerce/core/browser/portlets/cart.py delete mode 100644 pcommerce/core/browser/portlets/configure.zcml delete mode 100644 pcommerce/core/browser/prices.pt delete mode 100644 pcommerce/core/browser/prices.py delete mode 100644 pcommerce/core/browser/product.pt delete mode 100644 pcommerce/core/browser/product.py delete mode 100644 pcommerce/core/browser/variation.pt delete mode 100644 pcommerce/core/browser/variation.py delete mode 100644 pcommerce/core/browser/variations.pt delete mode 100644 pcommerce/core/browser/variations.py delete mode 100644 pcommerce/core/browser/viewlets/__init__.py delete mode 100644 pcommerce/core/browser/viewlets/buy.pt delete mode 100644 pcommerce/core/browser/viewlets/buy.py delete mode 100644 pcommerce/core/browser/viewlets/configure.zcml delete mode 100644 pcommerce/core/browser/viewlets/hot.pt delete mode 100644 pcommerce/core/browser/viewlets/hot.py delete mode 100644 pcommerce/core/browser/viewlets/info.pt delete mode 100644 pcommerce/core/browser/viewlets/info.py delete mode 100644 pcommerce/core/browser/viewlets/new.pt delete mode 100644 pcommerce/core/browser/viewlets/new.py delete mode 100644 pcommerce/core/browser/viewlets/processor.py delete mode 100644 pcommerce/core/browser/viewlets/related.pt delete mode 100644 pcommerce/core/browser/viewlets/related.py delete mode 100644 pcommerce/core/browser/viewlets/variation.pt delete mode 100644 pcommerce/core/browser/viewlets/variation.py delete mode 100644 pcommerce/core/cart.py delete mode 100644 pcommerce/core/charge.py delete mode 100644 pcommerce/core/config.py delete mode 100644 pcommerce/core/configure.zcml delete mode 100644 pcommerce/core/content/__init__.py delete mode 100644 pcommerce/core/content/price.py delete mode 100644 pcommerce/core/content/product.py delete mode 100644 pcommerce/core/content/variation.py delete mode 100644 pcommerce/core/currency.py delete mode 100644 pcommerce/core/data.py delete mode 100644 pcommerce/core/events.py delete mode 100644 pcommerce/core/interfaces.py delete mode 100644 pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po delete mode 100644 pcommerce/core/locales/de/LC_MESSAGES/plone.po delete mode 100644 pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po delete mode 100644 pcommerce/core/locales/es/LC_MESSAGES/plone.po delete mode 100755 pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po delete mode 100755 pcommerce/core/locales/fr/LC_MESSAGES/plone.po delete mode 100644 pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po delete mode 100644 pcommerce/core/locales/nl/LC_MESSAGES/plone.po delete mode 100644 pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po delete mode 100644 pcommerce/core/locales/no/LC_MESSAGES/plone.po delete mode 100644 pcommerce/core/locales/pcommerce.pot delete mode 100644 pcommerce/core/locales/plone.pot delete mode 100644 pcommerce/core/order.py delete mode 100644 pcommerce/core/permissions.zcml delete mode 100644 pcommerce/core/plone3.py delete mode 100644 pcommerce/core/processor.py delete mode 100644 pcommerce/core/profiles/default/actions.xml delete mode 100644 pcommerce/core/profiles/default/catalog.xml delete mode 100644 pcommerce/core/profiles/default/controlpanel.xml delete mode 100644 pcommerce/core/profiles/default/cssregistry.xml delete mode 100644 pcommerce/core/profiles/default/factorytool.xml delete mode 100644 pcommerce/core/profiles/default/jsregistry.xml delete mode 100644 pcommerce/core/profiles/default/metadata.xml delete mode 100644 pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt delete mode 100644 pcommerce/core/profiles/default/portlets.xml delete mode 100644 pcommerce/core/profiles/default/propertiestool.xml delete mode 100644 pcommerce/core/profiles/default/rolemap.xml delete mode 100644 pcommerce/core/profiles/default/skins.xml delete mode 100644 pcommerce/core/profiles/default/types.xml delete mode 100644 pcommerce/core/profiles/default/types/Folder.xml delete mode 100644 pcommerce/core/profiles/default/types/Price.xml delete mode 100644 pcommerce/core/profiles/default/types/Product.xml delete mode 100644 pcommerce/core/profiles/default/types/Variation.xml delete mode 100644 pcommerce/core/profiles/default/viewlets.xml delete mode 100644 pcommerce/core/registry.py delete mode 100644 pcommerce/core/required.py delete mode 100644 pcommerce/core/setuphandlers.py delete mode 100644 pcommerce/core/skins/pcommerce/pcommerce.css.dtml delete mode 100644 pcommerce/core/steps.py delete mode 100644 pcommerce/core/vocabulary.py diff --git a/pcommerce/__init__.py b/pcommerce/__init__.py deleted file mode 100644 index f48ad10..0000000 --- a/pcommerce/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - __path__ = extend_path(__path__, __name__) diff --git a/pcommerce/core/__init__.py b/pcommerce/core/__init__.py deleted file mode 100644 index 54cb61a..0000000 --- a/pcommerce/core/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Main product initializer -""" - -from pcommerce.core.config import PROJECTNAME, permissions - -from Products.Archetypes import atapi -from Products.CMFCore import utils as cmfutils -from Products.CMFCore.utils import getToolByName - -from zope.i18nmessageid import MessageFactory -PCommerceMessageFactory = MessageFactory('pcommerce') - -def initialize(context): - - from content import product, variation, price - - content_types, constructors, ftis = atapi.process_types( - atapi.listTypes(PROJECTNAME), - PROJECTNAME) - - for atype, constructor in zip(content_types, constructors): - cmfutils.ContentInit("%s: %s" % (PROJECTNAME, atype.portal_type), - content_types = (atype,), - permission = permissions[atype.portal_type], - extra_constructors = (constructor,), - ).initialize(context) \ No newline at end of file diff --git a/pcommerce/core/adapters.py b/pcommerce/core/adapters.py deleted file mode 100644 index 84d0107..0000000 --- a/pcommerce/core/adapters.py +++ /dev/null @@ -1,150 +0,0 @@ -from Acquisition import aq_parent - -from zope.interface import implements, Interface -from zope.component import adapts, getMultiAdapter -from zope.annotation.interfaces import IAnnotations - -from Products.CMFCore.utils import getToolByName -from Products.ATContentTypes.interface.image import IImageContent - -from pcommerce.core import interfaces - -ANNOTATIONS_KEY_TAXES = 'pcommerce.core.taxes' -ANNOTATIONS_KEY_TAX_INCLUDED = 'pcommerce.core.tax_included' - -class Imaging(object): - """ An adapter to handle the images of a product - """ - implements(interfaces.IImaging) - adapts(interfaces.IProduct) - - def __init__(self, context): - self.context = context - - def getImages(self): - """ All image inside of the product - """ - catalog = getToolByName(self.context, 'portal_catalog') - images = catalog(object_provides=IImageContent.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), - 'depth': 1}) - return images - -class Pricing(object): - """ An adapter to handle prices of a product - """ - implements(interfaces.IPricing) - adapts(interfaces.IProduct) - - def __init__(self, context): - self.context = context - - def getPrice(self, variations=[]): - """ The product price in combination of variations - """ - price = 0 - if self.context.getPrice() is not None: - price = float(self.context.getPrice()) - catalog = getToolByName(self.context, 'portal_catalog') - prices = [float(p.getPrice or 0) for p in catalog(object_provides=interfaces.IPrice.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()),'depth': 1})] - prices.append(price) - if len(prices)>0: - price = min(prices) - add = 0 - prices = [] - if len(variations): - for variation in variations: - if variation.getAddPrice(): - add += float(variation.getPrice()) - else: - v_prices = [float(v.getPrice or 0) for v in catalog(object_provides=interfaces.IPrice.__identifier__, path={'query': '/'.join(variation.getPhysicalPath()),'depth': 1})] - if variation.getPrice() is not None: - v_prices.append(float(variation.getPrice())) - if len(v_prices)>0: - prices.append(min(v_prices)) - - if len(prices)>0 and float(price) < float(max(prices)): - price = max(prices) - return float(price) + float(add) - - def getBasePrice(self, variations=[]): - """ The base price defined on the product - """ - return float(self.context.getPrice() or 0) - -class Taxes(object): - """ An adapter to handle taxes based on zones - - len(Taxes) - Taxes.has_key(key) - Taxes.items() - Taxes[key] - Taxes[key] = value - del(Taxes[key]) - """ - implements(interfaces.ITaxes) - adapts(Interface) - - _items = {} - _taxincl = None - - def __init__(self, context): - self.context = context - self.portal = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').portal() - annotations = IAnnotations(self.portal) - self._items = dict(annotations.get(ANNOTATIONS_KEY_TAXES, ())) - self._taxincl = annotations.get(ANNOTATIONS_KEY_TAX_INCLUDED, None) - - def __len__(self): - return len(self._items) - - def __getitem__(self, key): - return self._items[key] - - def __setitem__(self, key, value): - if not isinstance(value[0], float): - raise AttributeError, 'value has to be a float got %s' % type(value[0]) - self._items[key] = value - self._save() - - def __delitem__(self, key): - del(self._items[key]) - self._save() - - def has_key(self, key): - return self._items.has_key(key) - - def items(self): - return self._items.items() - - def keys(self): - return self._items.keys() - - def get_taxincl(self): - return self._taxincl - - def set_taxincl(self, value): - self._taxincl = value - annotations = IAnnotations(self.portal) - annotations[ANNOTATIONS_KEY_TAX_INCLUDED] = self._taxincl - - def del_taxincl(self): - del self._taxincl - annotations = IAnnotations(self.portal) - annotations[ANNOTATIONS_KEY_TAX_INCLUDED] = None - - taxincl = property(get_taxincl, set_taxincl, del_taxincl, "I'm the 'tax_incl' property.") - - - def edit(self, taxes): - """ edits the taxes - - taxes has to be a list of dicts with keys 'zone', 'tax' and 'taxname' - """ - self._items = {} - self._save() - for tax in taxes: - self[tax['zone']] = (tax['tax'], tax['taxname']) - - def _save(self): - annotations = IAnnotations(self.portal) - annotations[ANNOTATIONS_KEY_TAXES] = self.items() diff --git a/pcommerce/core/address.py b/pcommerce/core/address.py deleted file mode 100644 index 52e2219..0000000 --- a/pcommerce/core/address.py +++ /dev/null @@ -1,108 +0,0 @@ -import re -from persistent import Persistent - -from zope.i18n import translate -from zope.interface import implements, Interface -from zope.component import adapts - -from Products.CMFPlone import PloneMessageFactory as _p -from Products.validation.validators.BaseValidators import EMAIL_RE -email_re = re.compile(EMAIL_RE) - -from pcommerce.core.interfaces import IAddress, IAddressFactory -from pcommerce.core import PCommerceMessageFactory as _ - -class Address(Persistent): - """""" - implements(IAddress) - - salutation = u'' - firstname = u'' - lastname = u'' - company = u'' - address1 = u'' - address2 = u'' - zip = u'' - city = u'' - country = u'' - zone = u'' - email = u'' - phone = u'' - - def __init__(self, - salutation, - firstname, - lastname, - company, - address1, - address2, - zip, - city, - country, - zone, - email, - phone): - """""" - self.salutation = salutation - self.firstname = firstname - self.lastname = lastname - self.company = company - self.address1 = address1 - self.address2 = address2 - self.zip = zip - self.city = city - self.country = country - self.zone = zone - self.email = email - self.phone = phone - - def mailInfo(self, request, lang=None, customer=False): - address = [(self.salutation and translate((self.salutation == 'mr' and _('Mr.') or _('Mrs. / Ms.')), context=request, target_language=lang) +' ' or '') + self.firstname +' '+ self.lastname, - self.company, - self.address1, - self.address2, - self.zip + (self.zip is not None and ' ') + self.city, - self.country, - self.zone] - address = [value for value in address if value] - address.append('') - address.append(self.email) - if self.phone: - address.append(self.phone) - return '\n'.join(address) - -class AddressFactory(object): - adapts(Interface) - implements(IAddressFactory) - - required = ('firstname', 'lastname', 'address1', 'city', 'country', 'phone') - - def __init__(self, request): - self.request = request - - def validate(self, tag): - errors = {} - required = self.required - data = self.request.get(tag, {}) - for field in required: - if not data.get(field, None): - errors[tag+'.'+field] = _p(u'This field is required, please provide some information.') - - if not email_re.match(data.get('email', '')): - errors[tag+'.'+'email'] = _p(u'Please submit a valid email address.') - return errors - - def create(self, tag): - data = self.request.get(tag, {}) - return Address(salutation = data.get('salutation', '').decode('utf-8'), - firstname = data.get('firstname', '').decode('utf-8'), - lastname = data.get('lastname', '').decode('utf-8'), - company = data.get('company', '').decode('utf-8'), - address1 = data.get('address1', '').decode('utf-8'), - address2 = data.get('address2', '').decode('utf-8'), - zip = data.get('zip', '').decode('utf-8'), - city = data.get('city', '').decode('utf-8'), - country = data.get('country', '').decode('utf-8'), - zone = data.get('zone', '').decode('utf-8'), - email = data.get('email', '').decode('utf-8'), - phone = data.get('phone', '').decode('utf-8'),) diff --git a/pcommerce/core/browser/__init__.py b/pcommerce/core/browser/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/browser/address.pt b/pcommerce/core/browser/address.pt deleted file mode 100644 index a8bc1a3..0000000 --- a/pcommerce/core/browser/address.pt +++ /dev/null @@ -1,348 +0,0 @@ - -
- -
- - - - -
-
-
-
-
-
-
-
-
- - -
-
- - - -
- The Error -
- -
- - -
-
- -
- - - - - (Required) - - -
- The Error -
- -
- -
-
- -
- - - - - (Required) - - -
- The Error -
- -
- -
-
- -
- - - -
- The Error -
- -
- -
-
- -
- - - - (Required) - - -
- The Error -
- -
- -
-
- -
- - -
- The Error -
- -
- -
-
- -
- - - - (Required) - - -
- The Error -
- -
- The Error -
- -
-
- - - -
-
-
- -
- - - - - (Required) - - -
- The Error -
- -
- -
-
- -
- - - - - (Required) - - -
- The Error -
- -
- -
-
- - - -
- - - - - (Required) - - -
- The Error -
- -
- -
-
- -
- - - - - (Required) - - -
- The Error -
- -
- -
-
-
-
- \ No newline at end of file diff --git a/pcommerce/core/browser/cart.pt b/pcommerce/core/browser/cart.pt deleted file mode 100644 index 3c08110..0000000 --- a/pcommerce/core/browser/cart.pt +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - -

- Your shopping cart -

- -

- Your shopping cart is empty -

- -
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProductAmountPricePrice totalRemove
- - - - - - - 50.00 - - 500.00 - - -
- Total - -   - -   - - - 500.00 - - -   -
-

- You have to be registered to check out your order, either - - log in - if you already - have an account or head over to the - - registration form - if you don't. -

-
- - -
-
- -
-
- - - diff --git a/pcommerce/core/browser/cart.py b/pcommerce/core/browser/cart.py deleted file mode 100644 index 39fdd9b..0000000 --- a/pcommerce/core/browser/cart.py +++ /dev/null @@ -1,49 +0,0 @@ -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from plone.memoize.instance import memoize - -from Products.CMFCore.utils import getToolByName - -from pcommerce.core.currency import CurrencyAware -from pcommerce.core.config import CheckOut -from pcommerce.core.interfaces import IShoppingCart, ITaxes - -class Cart(BrowserView): - """view of the shopping cart - """ - - template = ViewPageTemplateFile('cart.pt') - - def __call__(self): - self.request.set('disable_border', 1) - self.cart = IShoppingCart(self.context) - return self.template() - - @property - @memoize - def size(self): - return self.cart.amount() - - @property - @memoize - def products(self): - return self.cart.getProducts() - - @property - @memoize - def checkout(self): - return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) - - @property - @memoize - def price(self): - return CurrencyAware(self.cart.getPrice()) - - @property - @memoize - def taxincl(self): - taxes = ITaxes(self.context) - return {'tax': taxes.taxincl[0], - 'taxname': taxes.taxincl[1]} - \ No newline at end of file diff --git a/pcommerce/core/browser/checkout.pt b/pcommerce/core/browser/checkout.pt deleted file mode 100644 index 60dafc6..0000000 --- a/pcommerce/core/browser/checkout.pt +++ /dev/null @@ -1,72 +0,0 @@ - - - - -
- -

- Check out -

-
- - - - - - -
-
-
-
-
-
- - - - - - - -
- - - -
- -
- -
- - - -
- - \ No newline at end of file diff --git a/pcommerce/core/browser/checkout.py b/pcommerce/core/browser/checkout.py deleted file mode 100644 index 37f0525..0000000 --- a/pcommerce/core/browser/checkout.py +++ /dev/null @@ -1,376 +0,0 @@ -import re - -from zope.component import getMultiAdapter -from zope.interface import implements - -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.CMFCore.utils import getToolByName -from Products.statusmessages.interfaces import IStatusMessage -from Products.validation.validators.BaseValidators import EMAIL_RE -email_re = re.compile(EMAIL_RE) - -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.config import INITIALIZED -from pcommerce.core.interfaces import IShoppingCart, IOrderRegistry, ISteps -from pcommerce.core.interfaces import ICheckoutView, IComponent, IOrder - -from pcommerce.core.order import ORDER_SESSION_KEY - - -class Checkout(BrowserView): - """checkout view - """ - implements(ICheckoutView) - - template = ViewPageTemplateFile('checkout.pt') - - errors = {} - cart = None - order = None - stepid = 0 - components = [] - redirect = None - - def __call__(self): - self.request.set('disable_border', 1) - self.errors = {} - - self.cart = IShoppingCart(self.context) - - if not len(self.cart): - statusmessage = IStatusMessage(self.request) - statusmessage.addStatusMessage(_(u'You have not yet added any ' - 'products to your cart'), 'error') - return self.request.RESPONSE.redirect('%s/@@cart' % - self.context.absolute_url()) - - if self.request.form.get('checkout.cancel', None): - return getMultiAdapter((self.context, self.request), - name=u'checkout.cancel')() - - self.stepid = int(self.request.form.get('checkout.stepid', 0)) - - temp_state = None - registry = IOrderRegistry(self.context) - self.order = registry.getOrder(self.request.SESSION.get( - ORDER_SESSION_KEY, 0)) - if self.order is not None and self.order.state != INITIALIZED: - temp_state = self.order.state - self.order.state = INITIALIZED - - self.order = IOrder(self.context) - - self._stepid_validator() - - if self.request.form.get('checkout.next') and \ - self.stepid < len(self.steps) - 1: - self.next() - elif self.request.form.get('checkout.previous') and self.stepid > 0: - self.previous() - elif self.request.get('stepid'): - self.gotostep(int(self.request.get('stepid', 0))) - - if self.redirect is not None: - return self.request.RESPONSE.redirect(self.redirect) - - html = self.template() - - if temp_state is not None: - self.order.state = temp_state - - if self.laststep: - registry = IOrderRegistry(self.context) - registry.send(self.order.orderid) - self.cart.clear() - return html - - @property - def steps(self): - return ISteps(self.context) - - def next(self): - self._nextstep() - while 1: - for component in self.components: - if component.renders(): - return - self._nextstep() - - def previous(self): - self._previousstep() - while 1: - for component in self.components: - if component.renders(): - return - self._previousstep() - - def gotostep(self, stepid): - self._gotostep(stepid) - renders = False - for component in self.components: - if component.renders(): - renders = True - if not renders: - self.gotostep(self.stepid + 1) - - def _nextstep(self): - if self.validate(): - self.process() - self.stepid += 1 - self._stepid_validator() - - def _previousstep(self): - self.stepid -= 1 - self._stepid_validator() - - def _gotostep(self, stepid): - self.stepid = stepid - self._stepid_validator() - - def _stepid_validator(self): - if self.stepid < 0: - self.stepid = 0 - self._initialize_components() - return - elif self.stepid > len(self.steps) - 1: - self.stepid = len(self.steps) - 1 - - for stepid in range(0, self.stepid): - if not stepid in self.order.processed_steps: - self.stepid = stepid - self._initialize_components() - return - - self._initialize_components() - - def _initialize_components(self): - self.components = [] - for name in self.steps[self.stepid]['components']: - component = getMultiAdapter((self.context, self.request), - interface=IComponent, name=name).__of__(self.context) - self.components.append(component) - return self.components - - def validate(self): - valid = True - for component in self.components: - if not component.validate(): - valid = False - return valid - - def process(self): - self.redirect = None - for component in self.components: - component.process() - if not (self.stepid in self.order.processed_steps): - self.order.processed_steps = self.order.processed_steps + \ - (self.stepid,) - for i in range(0, len(self.steps)): - step = self.steps[i] - for name in step['components']: - s_component = getMultiAdapter( - (self.context, self.request), interface=IComponent, - name=name).__of__(self.context) - if component.__name__ in s_component.dependencies: - self.order.processed_steps = \ - tuple([n for n in self.order.processed_steps - if not n == i]) - if hasattr(component, 'action'): - action = component.action() - if action: - self.redirect = action - - def renders(self, step): - components = [] - for name in step['components']: - component = getMultiAdapter((self.context, self.request), - interface=IComponent, name=name).__of__(self.context) - if component.renders(): - return True - return False - - @property - def stepnavigation(self): - steps = [] - step = None - - for i in range(0, len(self.steps)): - step = self.steps[i] - if len(steps) and step['name'] == steps[-1]['name']: - continue - renders = False - for name in step['components']: - component = getMultiAdapter((self.context, self.request), - interface=IComponent, name=name).__of__(self.context) - if component.renders(): - renders = True - if not renders: - continue - - selected = False - if step['name'] == self.steps[self.stepid]['name']: - selected = True - - _class = 'step' - if i == 0: - _class += ' first' - elif i == (len(self.steps) - 1): - _class += ' last' - if selected: - _class += ' select' - if i < self.stepid: - _class += ' passed' - if i in self.order.processed_steps: - _class += ' processed' - href = None - if (i in self.order.processed_steps or \ - (i - 1) in self.order.processed_steps) and \ - not selected and not self.laststep: - href = '%s/@@checkout?stepid=%s' % ( - self.context.absolute_url(), i) - - steps.append({'stepid': str(i), - 'name': step['name'], - 'selected': selected, - 'href': href, - 'class': _class, }) - return steps - - @property - def previous_label(self): - for component in self.components: - if hasattr(component, 'previous_label'): - return component.previous_label - if self.laststep: - return _(u'Print') - return _(u'Previous step') - - @property - def next_label(self): - for component in self.components: - if hasattr(component, 'next_label'): - return component.next_label - if self.laststep: - return _(u'Continue shopping') - if self.stepid == len(self.steps) - 2: - return _(u'Send order') - return _(u'Next step') - - @property - def cancel_label(self): - for component in self.components: - if hasattr(component, 'cancel_label'): - return component.cancel_label - return _(u'Cancel checkout') - - @property - def previous_onclick(self): - for component in self.components: - if hasattr(component, 'previous_onclick'): - return component.previous_onclick - if self.laststep: - return "print()" - return None - - @property - def next_onclick(self): - for component in self.components: - if hasattr(component, 'next_onclick'): - return component.next_onclick - return None - - @property - def cancel_onclick(self): - for component in self.components: - if hasattr(component, 'cancel_onclick'): - return component.cancel_onclick - return None - - @property - def action(self): - if self.laststep: - props = getToolByName(self.context, - 'portal_properties').pcommerce_properties - portal_state = getMultiAdapter((self.context, self.request), - name=u'plone_portal_state') - return '%s/%s' % (portal_state.portal_url(), - props.getProperty('post_checkout', '')) - return self.context.absolute_url() + '/@@checkout' - - @property - def laststep(self): - return self.stepid == len(self.steps) - 1 - - -class PaymentFailed(BrowserView): - """ Payment failed - """ - - def __call__(self): - order = IOrder(self.context) - m = len(order.processed_steps) and max(order.processed_steps) or 0 - order.processed_steps = tuple( - [n for n in order.processed_steps if n != m]) - statusmessage = IStatusMessage(self.request) - statusmessage.addStatusMessage(_(u'Payment failed'), 'error') - return self.request.RESPONSE.redirect('%s/@@checkout?stepid=%s' % ( - self.context.absolute_url(), m)) - - -class PaymentCancel(BrowserView): - """ Payment canceled - """ - - def __call__(self): - order = IOrder(self.context) - m = len(order.processed_steps) and max(order.processed_steps) or 0 - order.processed_steps = tuple( - [n for n in order.processed_steps if n != m]) - statusmessage = IStatusMessage(self.request) - statusmessage.addStatusMessage(_(u'Payment canceled'), 'error') - return self.request.RESPONSE.redirect('%s/@@checkout?stepid=%s' % ( - self.context.absolute_url(), m)) - - -class PaymentSuccess(BrowserView): - """ Payment successful - """ - - def __call__(self): - registry = IOrderRegistry(self.context) - order = registry.getOrder( - self.request.SESSION.get(ORDER_SESSION_KEY, 0)) - return self.request.RESPONSE.redirect( - '%s/@@checkout?checkout.stepid=%s' % ( - self.context.absolute_url(), - max(order.processed_steps) + 1)) - - -class CheckoutCancel(BrowserView): - """checkout cancel view - """ - - def __call__(self): - registry = IOrderRegistry(self.context) - registry.cancel(self.request.SESSION.get(ORDER_SESSION_KEY, 0)) - statusmessage = IStatusMessage(self.request) - statusmessage.addStatusMessage( - _('message_checkout_canceled', default=u'Check out canceled'), - 'info') - return self.request.RESPONSE.redirect('%s/@@cart' % - self.context.absolute_url()) - - -class CheckoutFailed(BrowserView): - """checkout failed view - """ - - def __call__(self): - registry = IOrderRegistry(self.context) - registry.fail(self.request.SESSION.get(ORDER_SESSION_KEY, 0)) - statusmessage = IStatusMessage(self.request) - statusmessage.addStatusMessage(_('message_checkout_failed', - default=u'Check out failed'), 'error') - return self.request.RESPONSE.redirect( - '%s/@@cart' % self.context.absolute_url()) diff --git a/pcommerce/core/browser/components/__init__.py b/pcommerce/core/browser/components/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/browser/components/address.pt b/pcommerce/core/browser/components/address.pt deleted file mode 100644 index 1e050f3..0000000 --- a/pcommerce/core/browser/components/address.pt +++ /dev/null @@ -1,17 +0,0 @@ - -
-

- Billing address -

- -
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/address.py b/pcommerce/core/browser/components/address.py deleted file mode 100644 index fb0d66b..0000000 --- a/pcommerce/core/browser/components/address.py +++ /dev/null @@ -1,26 +0,0 @@ -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.CMFPlone import PloneMessageFactory as _p - -from pcommerce.core.browser.components.base import BaseComponent -from pcommerce.core import interfaces - -class AddressComponent(BaseComponent): - index = ViewPageTemplateFile('address.pt') - - def validate(self): - self.errors = {} - factory = interfaces.IAddressFactory(self.request) - self.errors = factory.validate('customer') - return len(self.errors) == 0 - - def process(self): - factory = interfaces.IAddressFactory(self.request) - self.order.address = factory.create('customer') - taxes = interfaces.ITaxes(self.context) - if self.order.address.zone and taxes.has_key(self.order.address.zone): - self.order.zone = (self.order.address.zone, taxes[self.order.address.zone]) - - @property - def address(self): - return self.order.address - \ No newline at end of file diff --git a/pcommerce/core/browser/components/base.py b/pcommerce/core/browser/components/base.py deleted file mode 100644 index 2913e91..0000000 --- a/pcommerce/core/browser/components/base.py +++ /dev/null @@ -1,273 +0,0 @@ -from zope.interface import implements, Interface -from zope.component import adapts, getMultiAdapter, queryMultiAdapter, getAdapter - -from plone.memoize.instance import memoize - -from Products.Five.browser import BrowserView - -from pcommerce.core import interfaces -from pcommerce.core.currency import CurrencyAware - -class BaseComponent(BrowserView): - implements(interfaces.IComponent) - adapts(Interface) - - errors = {} - cart = None - order = None - dependencies = () - - def __init__(self, context, request): - self.context = context - self.request = request - self.order = interfaces.IOrder(self.context) - self.cart = interfaces.IShoppingCart(self.context) - - def __call__(self): - return self.index() - - def _shipments(self): - registry = interfaces.IShipmentRegistry(self.context) - return registry.getShipmentMethods() - - def _shipmentgroups(self): - groups = {} - products = self.products - available_shipmentids = self._shipments() - for product in products: - product = product['object'] - shipmentids = product.getShipments() - shipmentids = [shipmentid for shipmentid in shipmentids if shipmentid in available_shipmentids] - shipmentids.sort() - shipmentids = tuple(shipmentids) - if groups.has_key(shipmentids): - groups[shipmentids].append(product) - else: - groups[shipmentids] = [product,] - return groups - - @property - def shipmentgroups(self): - group = [] - shipmentgroups = self._shipmentgroups() - shipments = self._shipments() - for shipmentids, products in shipmentgroups.items(): - mapping = [] - for id in shipmentids: - if shipments.has_key(id): - shipment = shipments[id] - - # check is selected - selected = False - uids = [] - for product in products: - uids.append(product.UID()) - uids = tuple(uids) - for shipment_id, products_uids in self.order.shipmentids.items(): - if shipment_id == id and products_uids == uids: - selected = True - break - - mapping.append({'id': id, - 'title': shipment.title, - 'description': shipment.description, - 'icon': shipment.icon, - 'logo': shipment.logo, - 'selected': selected}) - group.append({'shipments': mapping, - 'products': products, - 'shipmentids': shipmentids, }) - return group - - @property - @memoize - def shipments(self): - shipments =[] - i = 1 - for shipmentid, products in self.order.shipmentids.items(): - shipment = getAdapter(self.context, name=shipmentid, interface=interfaces.IShipmentMethod) - data = {'id': shipmentid, - 'plugin': shipment, - 'title': shipment.title, - 'description': shipment.description, - 'icon': shipment.icon, - 'logo': shipment.logo, - 'products': products, - 'renders': False, - 'view': None, - 'number': i} - shipmentview = queryMultiAdapter((shipment, self.request), name=self.__name__, interface=interfaces.IShipmentView) - if shipmentview is not None: - data['view'] = shipmentview.__of__(self.context) - data['renders'] = data['view'].renders() - shipments.append(data) - i += 1 - return shipments - - def _payments(self): - registry = interfaces.IPaymentRegistry(self.context) - return registry.getPaymentMethods() - - @property - def payments(self): - payments = [] - for name, payment in self._payments().items(): - selected = False - if name == self.order.paymentid: - selected = True - payments.append({'id': name, - 'plugin': payment, - 'title': payment.title, - 'description': payment.description, - 'icon': payment.icon, - 'logo': payment.logo, - 'selected': selected}) - return payments - - @property - def payment(self): - payment = self._payments().get(self.order.paymentid, None) - if payment is None: - return None - data = {'id': self.order.paymentid, - 'plugin': payment, - 'title': payment.title, - 'description': payment.description, - 'icon': payment.icon, - 'logo': payment.logo, - 'view': None} - view = queryMultiAdapter((payment, self.request), name=self.__name__, interface=interfaces.IPaymentView) - if view is not None: - data['view'] = view.__of__(self.context) - return data - - @property - @memoize - def paymentview(self): - return self.payment and self.payment['view'] or None - - def action(self): - if self.paymentview is not None: - if hasattr(self.paymentview, 'action'): - return self.paymentview.action() - return None - - @property - def products(self): - return self.cart.getProducts() - - def getProductNumber(self, uid): - if len(self.shipments) == 1: - return None - for shipment in self.shipments: - if uid in shipment['products']: - return shipment['number'] - return None - - @property - def price(self): - if self.order: - return CurrencyAware(self.order.price) - return CurrencyAware(self.cart.getPrice()) - - @property - def pricetax(self): - if self.order: - return CurrencyAware(self.order.pricetax) - return None - - @property - def pricetaxincl(self): - if self.order: - return CurrencyAware(self.order.pricetaxincl) - return None - - @property - def pretaxcharges(self): - charges = [] - if getattr(self.order.paymentdata, 'pretaxcharge', 0): - charges.append({'title': self.payment['title'], - 'price': CurrencyAware(getattr(self.order.paymentdata, 'pretaxcharge', 0))}) - for shipmentid, data in self.order.shipmentdata.items(): - if not data.pretaxcharge: - continue - for shipment in self.shipments: - if shipmentid == shipment['id']: - charges.append({'title': shipment['title'], - 'number': len(self.shipments) > 1 and shipment['number'] or None, - 'price': CurrencyAware(data.pretaxcharge)}) - for charge in self.order.pretaxcharges: - if charge.price: - charges.append({'title': charge.title, - 'price': CurrencyAware(charge.price)}) - return charges - - @property - def subtotal(self): - if self.order.pretaxcharge: - return CurrencyAware(self.order.subtotal) - return None - - @property - def posttaxcharges(self): - charges = [] - if getattr(self.order.paymentdata, 'posttaxcharge', 0): - charges.append({'title': self.payment['title'], - 'price': CurrencyAware(getattr(self.order.paymentdata, 'posttaxcharge', 0))}) - for shipmentid, data in self.order.shipmentdata.items(): - if not data.posttaxcharge: - continue - for shipment in self.shipments: - if shipmentid == shipment['id']: - charges.append({'title': shipment['title'], - 'number': len(self.shipments) > 1 and shipment['number'] or None, - 'price': CurrencyAware(data.posttaxcharge)}) - for charge in self.order.posttaxcharges: - if charge.price: - charges.append({'title': charge.title, - 'price': CurrencyAware(charge.price)}) - return charges - - @property - def totalincl(self): - if self.order.posttaxcharge: - return CurrencyAware(self.order.totalincl) - return None - - @property - def taxincl(self): - if self.order: - return self.order.taxincl - return None - - @property - def taxinclname(self): - if self.order: - return self.order.taxinclname - return None - - @property - def tax(self): - if self.order: - return self.order.tax - return None - - @property - def taxname(self): - if self.order: - return self.order.taxname - return None - - @property - def total(self): - if self.order: - return CurrencyAware(self.order.total) - return None - - @property - def zones(self): - taxes = interfaces.ITaxes(self.context) - return taxes.keys() - - def renders(self): - return True diff --git a/pcommerce/core/browser/components/configure.zcml b/pcommerce/core/browser/components/configure.zcml deleted file mode 100644 index bd6f987..0000000 --- a/pcommerce/core/browser/components/configure.zcml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/pcommerce/core/browser/components/confirmation.pt b/pcommerce/core/browser/components/confirmation.pt deleted file mode 100644 index f79c22b..0000000 --- a/pcommerce/core/browser/components/confirmation.pt +++ /dev/null @@ -1,63 +0,0 @@ - -
-
- Thank you! -
-
- We successfully received your order. An Email has been sent to you containing all the order details. -
-
-
-

- Confirmation -

-
-
-

- Billing address -

- -
- -
-

- Shipment -

- -
- -

- Title - 1 -

- -
-
-
- -
-

- Payment -

- -

- Title -

- -
-
- - -
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/confirmation.py b/pcommerce/core/browser/components/confirmation.py deleted file mode 100644 index 5cdafbb..0000000 --- a/pcommerce/core/browser/components/confirmation.py +++ /dev/null @@ -1,16 +0,0 @@ -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.browser.components.base import BaseComponent - -class ConfirmationComponent(BaseComponent): - index = ViewPageTemplateFile('confirmation.pt') - - def validate(self): - return True - - def process(self): - return - - @property - def address(self): - return self.order.address diff --git a/pcommerce/core/browser/components/gtc.pt b/pcommerce/core/browser/components/gtc.pt deleted file mode 100644 index 243d98a..0000000 --- a/pcommerce/core/browser/components/gtc.pt +++ /dev/null @@ -1,28 +0,0 @@ - -
-
-
- The Error -
- - - (Required) - -
-
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/gtc.py b/pcommerce/core/browser/components/gtc.py deleted file mode 100644 index 11b1d62..0000000 --- a/pcommerce/core/browser/components/gtc.py +++ /dev/null @@ -1,27 +0,0 @@ -from zope.component import getMultiAdapter -from plone.memoize.instance import memoize - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.CMFCore.utils import getToolByName - -from pcommerce.core.browser.components.base import BaseComponent -from pcommerce.core import PCommerceMessageFactory as _ - -class GTCComponent(BaseComponent): - index = ViewPageTemplateFile('gtc.pt') - - def validate(self): - self.errors = {} - if self.request.form.get('gtc'): - return True - self.errors['gtc'] = _('The general terms and conditions have to be accepted to finish your check out.') - return False - - def process(self): - return - - @memoize - def gtc(self): - props = getToolByName(self.context, 'portal_properties').pcommerce_properties - portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') - return '%s/%s' % (portal_state.portal_url(), props.getProperty('gtc', '')) diff --git a/pcommerce/core/browser/components/overview.pt b/pcommerce/core/browser/components/overview.pt deleted file mode 100644 index b197c5c..0000000 --- a/pcommerce/core/browser/components/overview.pt +++ /dev/null @@ -1,55 +0,0 @@ - -
-

- Overview -

-
-
-

- Billing address -

- -
- -
-

- Shipment -

- -
- -

- Title - 1 -

- -
-
-
- -
-

- Payment -

- -

- Title -

- -
-
- - -
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/overview.py b/pcommerce/core/browser/components/overview.py deleted file mode 100644 index eade921..0000000 --- a/pcommerce/core/browser/components/overview.py +++ /dev/null @@ -1,16 +0,0 @@ -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.browser.components.base import BaseComponent - -class OverviewComponent(BaseComponent): - index = ViewPageTemplateFile('overview.pt') - - def validate(self): - return True - - def process(self): - return - - @property - def address(self): - return self.order.address diff --git a/pcommerce/core/browser/components/payment.pt b/pcommerce/core/browser/components/payment.pt deleted file mode 100644 index f61507d..0000000 --- a/pcommerce/core/browser/components/payment.pt +++ /dev/null @@ -1,17 +0,0 @@ - -
-

- Payment -

- - -
- diff --git a/pcommerce/core/browser/components/payment.py b/pcommerce/core/browser/components/payment.py deleted file mode 100644 index 6d5ae83..0000000 --- a/pcommerce/core/browser/components/payment.py +++ /dev/null @@ -1,27 +0,0 @@ -from zope.component import queryMultiAdapter - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.interfaces import IPaymentView -from pcommerce.core.browser.components.base import BaseComponent - -class PaymentComponent(BaseComponent): - index = ViewPageTemplateFile('payment.pt') - - dependencies = ('payments',) - - def validate(self): - return self.paymentview and self.paymentview.validate() - - def process(self): - if self.paymentview: - self.order.paymentdata = self.paymentview.process() - - def renders(self): - if self.paymentview and self.paymentview.renders(): - return True - if len(self._payments()) == 1: - paymentview = queryMultiAdapter((self._payments().values()[0], self.request), name=self.__name__, interface=IPaymentView) - if paymentview is not None: - return paymentview.__of__(self.context).renders() - return False \ No newline at end of file diff --git a/pcommerce/core/browser/components/payments.pt b/pcommerce/core/browser/components/payments.pt deleted file mode 100644 index bbe166f..0000000 --- a/pcommerce/core/browser/components/payments.pt +++ /dev/null @@ -1,38 +0,0 @@ - -
-

- Payment -

-

- Select the desired payment method -

-
-
- The Error -
-
    - -
  • - -
  • -
    -
-
-
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/payments.py b/pcommerce/core/browser/components/payments.py deleted file mode 100644 index 452f65a..0000000 --- a/pcommerce/core/browser/components/payments.py +++ /dev/null @@ -1,29 +0,0 @@ -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.browser.components.base import BaseComponent -from pcommerce.core import PCommerceMessageFactory as _ - -class PaymentsComponent(BaseComponent): - index = ViewPageTemplateFile('payments.pt') - error = None - - def validate(self): - self.error = None - if len(self._payments()) == 1: - return True - id = self.request.form.get('payment_id') - if id is not None and self._payments().has_key(id): - return True - self.error = _(u'Please select a payment method.') - return False - - def process(self): - id = self.request.form.get('payment_id', len(self._payments()) == 1 and self.payments[0]['id']) - self.order.paymentid = id - if self.order.paymentdata and not self.order.paymentdata.id == id: - self.order.paymentdata = None - - def renders(self): - if len(self._payments())>1: - return True - return False diff --git a/pcommerce/core/browser/components/shipment.pt b/pcommerce/core/browser/components/shipment.pt deleted file mode 100644 index bf55915..0000000 --- a/pcommerce/core/browser/components/shipment.pt +++ /dev/null @@ -1,26 +0,0 @@ - -
-

- Shipment -

- -
-

- Title -

- - -
-
-
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/shipment.py b/pcommerce/core/browser/components/shipment.py deleted file mode 100644 index 130b418..0000000 --- a/pcommerce/core/browser/components/shipment.py +++ /dev/null @@ -1,50 +0,0 @@ -from persistent.mapping import PersistentMapping - -from zope.component import queryMultiAdapter - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.interfaces import IShipmentView -from pcommerce.core.browser.components.base import BaseComponent - -class ShipmentComponent(BaseComponent): - index = ViewPageTemplateFile('shipment.pt') - - dependencies = ('shipments',) - - def validate(self): - valid = True - for shipment in self.shipments: - if shipment['view'] is not None: - if not shipment['view'].validate(): - valid = False - return valid - - def process(self): - self.order.shipmentdata = PersistentMapping() - for shipment in self.shipments: - if shipment['view'] is not None: - shipmentdata = shipment['view'].process() - self.order.shipmentdata[shipmentdata.id] = shipmentdata - - def renders(self): - for shipment in self.shipments: - if shipment['renders']: - return True - for shipmentids in self._shipmentgroups().keys(): - if not len(shipmentids) == 1: - continue - shipmentview = queryMultiAdapter((self._shipments()[shipmentids[0]], self.request), name=self.__name__, interface=IShipmentView) - if shipmentview is not None: - if shipmentview.__of__(self.context).renders(): - return True - return False - - @property - def multiple(self): - count = 0 - for shipment in self.shipments: - if shipment['renders']: - count += 1 - return count > 1 - diff --git a/pcommerce/core/browser/components/shipments.pt b/pcommerce/core/browser/components/shipments.pt deleted file mode 100644 index 995f77a..0000000 --- a/pcommerce/core/browser/components/shipments.pt +++ /dev/null @@ -1,89 +0,0 @@ - -
-

- Shipment -

- -

- Select the desired shipment method -

- -
-
- The Error -
- - - -
    - -
  • - -
  • -
    -
-
-
-
- - - -
-

- Select the desired shipment method for the following products: -

-
    -
  • - - -
  • -
-
- The Error -
-
    - -
  • - -
  • -
    -
-
-
-
-
- \ No newline at end of file diff --git a/pcommerce/core/browser/components/shipments.py b/pcommerce/core/browser/components/shipments.py deleted file mode 100644 index 62b495b..0000000 --- a/pcommerce/core/browser/components/shipments.py +++ /dev/null @@ -1,63 +0,0 @@ -from persistent.mapping import PersistentMapping - -from plone.memoize.instance import memoize - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.browser.components.base import BaseComponent -from pcommerce.core import PCommerceMessageFactory as _ - -class ShipmentsComponent(BaseComponent): - index = ViewPageTemplateFile('shipments.pt') - - @property - @memoize - def selection(self): - return dict([(value['products'], value['shipmentid']) for key, value in self.request.form.items() if key.startswith('shipment_id_') and value.has_key('shipmentid')]) - - def validate(self): - self.errors = {} - valid = True - for shipmentids, products in self._shipmentgroups().items(): - if len(shipmentids) > 1: - key = tuple([p.UID() for p in products]) - if not self.selection.has_key(key): - self.errors[shipmentids] = _(u'Please select a shipment method.') - valid = False - elif not self.selection[key] in shipmentids: - self.errors[shipmentids] = _(u'Please select a shipment method.') - valid = False - return valid - - def process(self): - self.order.shipmentids = PersistentMapping() - for shipmentids, products in self._shipmentgroups().items(): - key = tuple([p.UID() for p in products]) - if len(shipmentids) > 1: - shipmentid = self.selection[key] - else: - shipmentid = shipmentids[0] - if not self.order.shipmentids.has_key(shipmentid): - self.order.shipmentids[shipmentid] = () - self.order.shipmentids[shipmentid] = self.order.shipmentids[shipmentid] + key - - def renders(self): - if len(self._shipments())==1: - return False - for shipments in self._shipmentgroups().keys(): - if len(shipments)>1: - return True - return False - - @property - def multiple(self): - shipmentsgroups = self._shipmentgroups() - if len(shipmentsgroups) == 1: - return False - count = 0 - for shipments in shipmentsgroups.keys(): - if len(shipments) > 1: - count = count+1 - if count > 1: - return True - return False diff --git a/pcommerce/core/browser/configlet.pt b/pcommerce/core/browser/configlet.pt deleted file mode 100644 index fd90b67..0000000 --- a/pcommerce/core/browser/configlet.pt +++ /dev/null @@ -1,250 +0,0 @@ - - - - -
- -

- PCommerce configuration -

- - - Up to Site Setup - - -
- -
- - - - - (Required) - - -
- The name appearing in payment-terminals -
- -
- The Error -
- -
- -
-
- -
- - - -
- The path to the page holding the general terms and conditions to accept before payment -
- -
- The Error -
- -
- -
-
- -
- - - -
- The path to the page to be redirected to after checkout -
- -
- The Error -
- -
- -
-
- -
- - - -
- The email address receiving and sending pcommerce related emails -
- -
- The Error -
- -
- -
-
- -
- Taxes - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ZoneTax nameTax factor
- - - - - - - - - - - The Error - -
- - - - - - - - - - The Error - -
-
- -
- Tax included in product price - - - - - - - - - - - - - - - -
Tax nameTax factor
- - - - - - The Error - -
-
- -
- - - -
- -
- -
- - - - diff --git a/pcommerce/core/browser/configlet.py b/pcommerce/core/browser/configlet.py deleted file mode 100644 index 068eabf..0000000 --- a/pcommerce/core/browser/configlet.py +++ /dev/null @@ -1,92 +0,0 @@ -from plone.memoize.instance import memoize - -from Products.statusmessages.interfaces import IStatusMessage -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone import PloneMessageFactory as _p - -from pcommerce.core.interfaces import ITaxes -from pcommerce.core import PCommerceMessageFactory as _ - -class PCommerceConfiglet(BrowserView): - """PCommerce configlet - """ - - template = ViewPageTemplateFile('configlet.pt') - properties = ('productname','gtc','post_checkout','email_address',) - values = {} - - def __call__(self): - self.request.set('disable_border', True) - self.errors = {} - - props = getToolByName(self.context, 'portal_properties').pcommerce_properties - if self.request.form.has_key('pcommerce_save'): - adapter = ITaxes(self.context) - taxes = [] - raw = self.request.form.get('taxes', []) - for tax in raw: - if not tax.has_key('remove') or not tax['remove']: - try: - tax = {'id': tax['id'], - 'tax': float(tax['tax']), - 'zone': tax['zone'], - 'taxname': tax['taxname']} - if tax['zone'] == '': - self.errors[tax['id']] = _(u'Please provide a zone name') - elif tax['taxname'] == '': - self.errors[tax['id']] = _(u'Please provide a tax name') - if not self.errors.has_key(tax['id']): - taxes.append(tax) - except: - self.errors[tax['id']] = _(u'Please enter a floating point number (e.g. 7.6)') - for prop in self.properties: - self.values[prop] = self.request.form.get(prop, '') - - - taxincl = None - tax = self.request.form.get('taxincl.tax', '') - taxname = self.request.form.get('taxincl.taxname', '') - - try: - if taxname == '' and tax != '': - self.errors['taxincl'] = _(u'Please provide a tax name') - else: - if tax == '': - tax = 0.0 - taxincl = (float(tax), taxname) - except: - self.errors['taxincl'] = _(u'Please enter a floating point number (e.g. 7.6)') - - if not self.errors: - adapter.edit(taxes) - adapter.taxincl = taxincl - IStatusMessage(self.request).addStatusMessage(_p('Properties saved'), 'info') - for prop in self.properties: - if prop == 'columns': - self.values[prop] = int(self.values[prop]) - props._setPropValue(prop, self.values[prop]) - else: - IStatusMessage(self.request).addStatusMessage(_p(u'Please correct the indicated errors'), 'error') - - for prop in self.properties: - self.values[prop] = props.getProperty(prop, '') - - return self.template() - - @property - @memoize - def taxes(self): - utils = getToolByName(self.context, 'plone_utils') - taxes = ITaxes(self.context) - return [{'id': utils.normalizeString(zone), - 'zone': zone, - 'tax': tax[0], - 'taxname': tax[1]} for zone, tax in taxes.items()] - - @property - def taxincl(self): - taxes = ITaxes(self.context) - return {'tax': taxes.taxincl[0], - 'taxname': taxes.taxincl[1]} diff --git a/pcommerce/core/browser/configure.zcml b/pcommerce/core/browser/configure.zcml deleted file mode 100644 index 701e734..0000000 --- a/pcommerce/core/browser/configure.zcml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pcommerce/core/browser/folder.pt b/pcommerce/core/browser/folder.pt deleted file mode 100644 index d75a24a..0000000 --- a/pcommerce/core/browser/folder.pt +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - -
- -
- -

- Title -

- -
- -
- Description -
- -
- -
- Portal status message -
- -
- -
- -
-
- -
- -
- -
- - - - - - \ No newline at end of file diff --git a/pcommerce/core/browser/folder.py b/pcommerce/core/browser/folder.py deleted file mode 100644 index 4a2649d..0000000 --- a/pcommerce/core/browser/folder.py +++ /dev/null @@ -1,92 +0,0 @@ -from Acquisition import aq_inner, aq_parent - -from zope.interface import implements - -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from Products.CMFCore.utils import getToolByName -from Products.ATContentTypes.interface.image import IImageContent - -from plone.memoize.instance import memoize -from plone.app.content import browser -from plone.app.content.batching import Batch - -from pcommerce.core.interfaces import IPricing, IShopFolder, IShop, IProduct -from pcommerce.core.currency import CurrencyAware - -batching_path = '/'.join(browser.__path__) - -class ShopHome(BrowserView): - """ shop home view - """ - implements(IShop) - - template = ViewPageTemplateFile('folder.pt') - - def __call__(self): - return self.template() - -class ShopFolderListing(BrowserView): - """ shop folder listing - """ - implements(IShopFolder) - - template = ViewPageTemplateFile('folder.pt') - batching = ViewPageTemplateFile('%s/batching.pt' % batching_path) - - def __call__(self): - self.page = int(self.request.get('pagenumber', 1)) - self.url = self.context.absolute_url() - return self.template() - - @property - @memoize - def batch(self): - catalog = getToolByName(self.context, 'portal_catalog') - portal_properties = getToolByName(self.context, 'portal_properties') - use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) - props = portal_properties.pcommerce_properties - columns = int(props.getProperty('columns', 3)) - width = int(props.getProperty('thumb_width', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - results = catalog(object_provides=IProduct.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), 'depth': 1}, sort_on='getObjPositionInParent') - items = [] - i = 0 - start = (self.page-1) * (columns * 5) - end = start + columns * 5 - for item in results: - url = item.getURL() - if item.portal_type in use_view_action: - url += '/view' - - if start <= i < end: - object = item.getObject() - col = i % columns + 1 - adapter = IPricing(object) - image = None - if object.getImage(): - image = {'caption': object.getImageCaption(), - 'thumb': '%s/%s' % (item.getURL(), width)} - - item = {'uid': item.UID, - 'class': 'col%s' % col, - 'title': item.Title, - 'description': item.Description, - 'price': CurrencyAware(adapter.getPrice()), - 'base_price': CurrencyAware(adapter.getBasePrice()), - 'offer': adapter.getPrice() < adapter.getBasePrice(), - 'image': image, - 'url': url} - else: - item = {'uid': item.UID, - 'title': item.Title, - 'description': item.Description, - 'url': url} - i += 1 - items.append(item) - return Batch(items, columns * 5, self.page, 5) - - @property - @memoize - def multiple_pages(self): - return self.batch.size > self.batch.pagesize diff --git a/pcommerce/core/browser/getprice.js b/pcommerce/core/browser/getprice.js deleted file mode 100644 index e0debb8..0000000 --- a/pcommerce/core/browser/getprice.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * PCommerce GetPrice - */ -jq('document').ready(function() { - - jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { - jq(this).find('option').each(function(i) { - html = jq(this).html(); - jq(this).html(html.substring(0, html.lastIndexOf('('))); - }); - }); - - if (jq('.buyViewlet select[name="cartVariation:list"]').length) { - pcommerceLoadPrice(); - } - jq('.buyViewlet select[name="cartVariation:list"]').change(function(){ - pcommerceLoadPrice(); - }); -}); - -function pcommerceLoadPrice(){ - var variations = []; - jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { - variations[i] = jq(this).attr('value'); - }); - jq('.portletInfoBox .priceInfo').load('getprice?v='+variations.join(',')); -} diff --git a/pcommerce/core/browser/getprice.pt b/pcommerce/core/browser/getprice.pt deleted file mode 100644 index 0aa3720..0000000 --- a/pcommerce/core/browser/getprice.pt +++ /dev/null @@ -1,8 +0,0 @@ - - - \ No newline at end of file diff --git a/pcommerce/core/browser/getprice.py b/pcommerce/core/browser/getprice.py deleted file mode 100644 index 9b7929b..0000000 --- a/pcommerce/core/browser/getprice.py +++ /dev/null @@ -1,40 +0,0 @@ -from Acquisition import aq_parent, aq_inner - -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from Products.CMFCore.utils import getToolByName - -from pcommerce.core.interfaces import IPricing, IProduct, IVariation -from pcommerce.core.currency import CurrencyAware - -class GetPrcie(BrowserView): - """ A AJAX interface for getPrece of the product - """ - - template = ViewPageTemplateFile('getprice.pt') - - def __call__(self): - return self.template() - - def price(self): - import logging - v_uid = None - product = aq_inner(self.context) - if IVariation.providedBy(product): - product = aq_parent(product) - v_uid = self.context.UID() - - v_uids = self.request.get('v', '') - v_uids = v_uids.split(',') - v_uids = [uid for uid in v_uids if uid != ''] - if not len(v_uids) and v_uid is not None: - v_uids = [v_uid,] - - catalog = getToolByName(self.context, 'uid_catalog') - variations = catalog(object_provides=IVariation.__identifier__, UID=v_uids) - variations = [variation.getObject() for variation in variations] - - price = IPricing(product).getPrice(variations) - - return CurrencyAware(price) \ No newline at end of file diff --git a/pcommerce/core/browser/images.pt b/pcommerce/core/browser/images.pt deleted file mode 100644 index dab07c3..0000000 --- a/pcommerce/core/browser/images.pt +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - -
- - - Add image - - -

- Images -

- -
-
Info
-
- You are currently looking at the images of a variation of the product - Product title. -
-
- -

- This product has no images. To add an image press the - 'add' button or paste content from another location. -

- -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
  Image  Modified  
- - - - - - - 08/19/2001 03:01 AM - - - - Edit -
- - - - -
- -
-
- - - - - - - diff --git a/pcommerce/core/browser/images.py b/pcommerce/core/browser/images.py deleted file mode 100644 index d56c459..0000000 --- a/pcommerce/core/browser/images.py +++ /dev/null @@ -1,52 +0,0 @@ -from zope.component import getMultiAdapter -from zope.interface import implements - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from Products.CMFCore.utils import getToolByName -from Products.ATContentTypes.interface.image import IImageContent - -from plone.memoize.instance import memoize -from plone.app.content.browser.interfaces import IFolderContentsView -from plone.app.content.browser.foldercontents import FolderContentsTable - -from pcommerce.core.browser.product import Product - -class Images(Product, FolderContentsTable): - """management view of all images - """ - implements(IFolderContentsView) - - template = ViewPageTemplateFile('images.pt') - - def __call__(self): - return self.template() - - @property - @memoize - def items(self): - catalog = getToolByName(self.context, 'portal_catalog') - plone_view = getMultiAdapter((self.context, self.request), name=u'plone') - utils = getToolByName(self.context, 'plone_utils') - wftool = getToolByName(self.context, 'portal_workflow') - results = catalog(object_provides=IImageContent.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), - 'depth': 1}) - images = [] - odd = True - for image in results: - images.append({'uid': image.UID, - 'id': image.getId, - 'modified': plone_view.toLocalizedTime(image.ModificationDate, long_format=1), - 'state_title': wftool.getTitleForStateOnType(image.review_state, image.portal_type), - 'state_class': 'state-' + utils.normalizeString(image.review_state), - 'is_expired': self.context.isExpired(image), - 'title_or_id': image.pretty_title_or_id(), - 'table_row_class': odd and 'odd' or 'even', - 'path': image.getPath, - 'relative_url': image.getURL(relative=True), - 'image_thumb': '%s/image_thumb' % image.getURL(), - 'url': {'edit': '%s/edit' % image.getURL(), - 'sharing': '%s/@@sharing' % image.getURL()}}) - """Thumb with height width parameters... ??? """ - odd = not odd - return images diff --git a/pcommerce/core/browser/images/price_icon.gif b/pcommerce/core/browser/images/price_icon.gif deleted file mode 100644 index 3013b1a48fe02deacc15f41c5e405c9a590964f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 595 zcmV-Z0<8T60c(C27U7=a{{P*AP z-N@&}rP-f*wsw}vk*v+Du-&Vo*PNKklaj}csM?}^xp|MoiLK77jl+ny;<9C|V6xt< zXRc$a+@oo#WsJjzhrxn}!h(gtfNG~_W~X6`!iIvpe%brOKmXqh5r)fPcAq(d5vExPx-KZCamJ#N@%woV(t)nZlQ++M%1xmWRKCd$)I@*qf5ZjFH5PT%cH~+oQ?lb`k)MgH2Ky9RY4blqE7Kacy;AA0CK!EGl{; zQv?imE;WQ}4pb)z1xgGX0|GOf6)?y%EKvTIqygv9YYm4i`hx4Y~tdbrf?EUj~SDGCFb zEShse3OYkTY#cX+j0xPpu?@B{$J{Z-9+-T;?D@NA`0jzhKAnF?@4w*n%e&%OIpOeE zI0y&DWDr=L--sgX_CXMox-`weJBq1JZ^jX@Y6!?1oWn}|{+jbbZ?<0y!#-3Bb84_^!V-h05&s!8xY?2E` z0Try7UHY45F*T&UfuZ`P(bIn0L@Mb5R#pg}nr_YkaEC{9#3Ujo&A&TG&cb~}M10OR z-k37|=8+J?QffQ`JLWiEc}dd3@lRj(O3R(1V)rBo)77OG=pdr?DH=k^Xk>x6(w`6f z6JY~;;o*s8e_End`ZQ38T;lc-9~&9kd`OJkRe17|&wGO%(-bu$;NX(CI4 zn6V}JRAGPcGqCrDbgZO*7GNd-0Q5gBJFztlf@ILaXZB}LKp7Zx{e{;bHe_zwzUAfp z-17+TS`~fw&X4ypE8eIXFa9E1xG(!H0%fBU+5N*FK`v>3&rk1b7zgtXQ1R_krHy@W zU)W1fQcg5w;X7=EYuqB%VEWaQn^UzeZ5otbxFh?+W6<-jl@jH&yG5mc?#h@ri68vF ze0yabgPs1-Ecq&>jPgsktDDzZD6S`edFvfA1T}L1sbR=UGHGWx^LWJlQp<@gIhSep z`;?u}?TYG1q1vrkl)ox-rHU6xZMd(m#LwWqYu}eoB^E6b57cyQs~*nabJ(xkE+4Bc hD}DkSb}(f*#H>bT)2pBV%Fgudak1WHrlmmz{{i~&8*%^u diff --git a/pcommerce/core/browser/images/variation_icon.gif b/pcommerce/core/browser/images/variation_icon.gif deleted file mode 100644 index 8a1291a7448f1fa25eec9f4eb160e55d4c80f334..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1048 zcmdVZ{ZrC+0KoAt%a-kS<UK7`>Bv>S&mB?39o{RPIh)s(`6H$^N4VIs%UIQFA#!gce@a+-NJ}`D0#o!9K~5{<0%7*_ethgxvAZ%Wzw znUYrF*U^mw6&60;B_Sea&ba7XhxqK6Am7F(sIFmN#$R}zl<1hXmf?Ecz1nH>(U^e( z79Ro|6-2Fw`Q9S0Ffer~g6K?xc#n#roomo@FsbJZr?fTYxF)CWh9?=ek;26Xl`u@T z@T!-eOM?a)@{|}57WB{L2cP1Te$~R*0hn8vK%T{;ROJ7i8K@hNuXV?;jf>7(jyRM z?Pl^e#)p}!GPhF~RPSs!*_*Xa-A7~p&u?Oijq8t9LWzy18Yj?uE|4&7 zXzc2>TZ&q<61+7fci*`4Bc - - - CHF 150.00 - instead of - CHF 200.00 - - - CHF 200.00 - - - - - - - - - Title - - 1 - - - - No - -
- -
Type:
-
Name
-
-
-
- -
-
- - - - - Title - - - Description - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProductAmountPricePrice total
- - - 10 - - 50.00 - - 500.00 -
- Total - -   - - - 500.00 - -
- Title - 1 - -   - - - 500.00 - -
- Total incl. charges - -   - - - 500.00 - -
- VAT - - % - - - 500.00 - -
- Total incl. - -   - - - 500.00 - -
- Title - 1 - -   - - - 500.00 - -
- Total incl. charges and - - Total incl. charges and % - - Total incl. charges - -   - - - 500.00 - -
-
- -
- -

- Title -

-

- Description -

-
- diff --git a/pcommerce/core/browser/manage_orders.pt b/pcommerce/core/browser/manage_orders.pt deleted file mode 100644 index 6d27ac9..0000000 --- a/pcommerce/core/browser/manage_orders.pt +++ /dev/null @@ -1,59 +0,0 @@ - - - - -

Manage orders

- - -

No orders were found.

-
- - - - - - - - - - - - - - - - - -
- - - â–² - â–¼ - -
- - - -
- -
- - - - - diff --git a/pcommerce/core/browser/order_details.pt b/pcommerce/core/browser/order_details.pt deleted file mode 100644 index 2b27abb..0000000 --- a/pcommerce/core/browser/order_details.pt +++ /dev/null @@ -1,53 +0,0 @@ - - - - - -

Order details

- - - Manage orders - - - -

Which one?

-

Please supply an order id. -

-
- - -

The order could not be found.

-

Please check the order id. -

-
- - -
- -
-
- -
- - - - - - diff --git a/pcommerce/core/browser/orders.py b/pcommerce/core/browser/orders.py deleted file mode 100644 index 34c1f66..0000000 --- a/pcommerce/core/browser/orders.py +++ /dev/null @@ -1,258 +0,0 @@ -import os - -from DateTime import DateTime - -from zope.i18n import translate - -from plone.app.content.batching import Batch -from plone.app.content.browser import tableview - -from Products.CMFCore.utils import getToolByName -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.currency import CurrencyAware -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.interfaces import IOrderRegistry - - -SESSION_KEY = 'pcommerce.core.manageorders.' - -class ManageOrders(BrowserView): - """Overview of all orders. - """ - - template = ViewPageTemplateFile('manage_orders.pt') - batching = ViewPageTemplateFile(os.path.join(os.path.dirname(tableview.__file__), 'batching.pt')) - - def __init__(self, *args, **kwargs): - super(ManageOrders, self).__init__(*args, **kwargs) - self.translation_service = getToolByName(self.context, - 'translation_service') - self.registry = IOrderRegistry(self.context) - self.pagesize = 20 - session = self.request.SESSION - self.pagenumber = session.get(SESSION_KEY + 'pagenumber', 1) - if self.request.get('pagenumber', None) is not None: - self.pagenumber = int(self.request.get('pagenumber')) - session.set(SESSION_KEY + 'pagenumber', self.pagenumber) - self.sort_on = session.get(SESSION_KEY + 'sort_on', 1) - self.reverse = session.get(SESSION_KEY + 'reverse', False) - if not self.request.get('sort_on', None) in ('getObjPositionInParent', '', None): - if self.request.get('sort_on', None) == self.sort_on: - self.reverse = not self.reverse - else: - self.reverse = False - self.sort_on = self.request.get('sort_on') - session.set(SESSION_KEY + 'reverse', self.reverse) - session.set(SESSION_KEY + 'sort_on', self.sort_on) - self.request.set('sort_on', '') - self.url = '%s/@@manage-orders' % self.context.absolute_url() - - def __call__(self): - self.request.set('disable_border', 1) - return self.template() - - def _translate_order_status_id(self, status_id): - """ - """ - order_status_string = { - 1: _('label_initialized', default="Initialized"), - 2: _('label_sent', default="Sent"), - 3: _('label_processed', default="Processed"), - 4: _('label_failed', default="Failed"), - 5: _('label_cancelled', default="Cancelled"), - } - return order_status_string[status_id] - - def order_fields(self): - """Fields and fieldnames to show in tables (order overviews / details). - - { 'field_id': '', - 'field_name': _("label_", default=""), - 'sortable': True - }, - """ - fields = [ - { 'field_id': 'orderid', - 'field_name': _("label_order_id", default="Order id"), - 'sortable': True - }, - { 'field_id': 'userid', - 'field_name': _("label_user_id", default="User id"), - 'sortable': True - }, - { 'field_id': 'date', - 'field_name': _("label_date", default="Date"), - 'sortable': True - }, - { 'field_id': 'currency', - 'field_name': _("label_currency", default="Currency"), - 'sortable': True - }, - { 'field_id': 'totalincl', - 'field_name': _("label_price_total", default="Price total"), - 'field_converter': self._totalincl_converter, - 'sortable': True - }, - { 'field_id': 'state', - 'field_name': _("label_order_state", default="Order status"), - 'sortable': True - }, - { 'field_id': 'zone', - 'field_name': _("label_zone", default="Zone"), - 'field_converter': self._zone_converter, - 'sortable': True - }, - { 'field_id': 'address', - 'field_name': _("label_address", default="Address"), - 'field_converter': self._address_converter, - 'sortable': True - }, - { 'field_id': 'products', - 'field_name': _("label_products", default="Products"), - 'field_converter': self._products_converter, - 'sortable': False - }, - { 'field_id': 'shipmentids', - 'field_name': _("label_shipmentids", default="Shipment id's"), - 'field_converter': self._shipmentids_converter, - 'sortable': False - }, - ] - return fields - - def _zone_converter(self, value, order): - return '%s (%s%% %s)' % (value[0], value[1][0], value[1][1]) - - def _totalincl_converter(self, value, order): - return CurrencyAware(value).valueToString() - - def _address_converter(self, value, order): - return '
%s
' % value.mailInfo(self.request) - - def _products_converter(self, value, order): - rows = [] - for product in value: - cells = [str(i) for i in product[1:5]] - cells.append(str(product[3]*product[4])) - rows.append('
'.join(cells)) - return ''' - - - - - - - -
%s
%s
''' % ('
'.join((translate(_(u'No'), context=self.request), - translate(_(u'Product'), context=self.request), - translate(_(u'Amount'), context=self.request), - translate(_(u'Price'), context=self.request), - translate(_(u'Price total'), context=self.request))), '
'.join(rows)) - - def _shipmentids_converter(self, value, order): - return '
  • %s
' % '
  • '.join(value.keys()) - - def order_management_columns(self): - """Fields for order management table. """ - field_ids = [ - 'orderid', - 'userid', - 'date', - 'currency', - 'totalincl', - 'state', - ] - columns = [ column for column in self.order_fields() if \ - column['field_id'] in field_ids] - return columns - - def _massageData(self, field_id, value): - """Modify the field values (if needed) for displaying to humans. """ - # Convert the date (float) to a DateTime format. - if field_id == 'date': - value = DateTime(value) - value = self.translation_service.ulocalized_time( - value, long_format=True, time_only=None, - context=self.context, domain='plonelocales', - request=self.request) - # Convert order status to a translated string - if field_id == 'state': - value = self._translate_order_status_id(value) - return value - - def _get_order_data(self, order_nr, fields): - """Returns data of a single order as as a list of dictionaries, - suitable for displaying in a page template. - - Copies only the specified fields (which are defined like the - _order_fields list of dicts above. - - [ { 'id': ..., # field id - 'value: ..., # field value - 'name': ..., # field name (optional) - }, - ] - """ - r_order = self.registry.getOrder(order_nr) - order_data = [] - sort = 0 - for field in fields: - field_data = {} - field_id = field['field_id'] - field_data['id'] = field_id - value = getattr(r_order, field_id) - if field_id == self.sort_on: - sort = value - if field.has_key('field_converter'): - try: - value = field['field_converter'](value, r_order) - except: - pass - field_data['value'] = self._massageData(field_id, value) - field_data['name'] = field['field_name'] - order_data.append(field_data) - return order_data, sort - - @property - def batch(self): - """Returns data rows for order management table. """ - orders = [] - sorting = [] - # use only selected fields in the table - columns = self.order_management_columns() - for order_nr in self.registry.getOrders(): - data, sort = self._get_order_data(order_nr, columns) - index = len(orders) - 1 - while index >= 0 and sort < sorting[index]: - index -= 1 - sorting.insert(index + 1, sort) - orders.insert(index + 1, data) - if self.reverse: - orders.reverse() - pagesize = self.pagesize - b = Batch(orders, - pagesize=pagesize, - pagenumber=self.pagenumber) - return b - -class OrderDetails(ManageOrders): - """View order details. - - Subclassed from ManageOrders for easy code reuse. - """ - template = ViewPageTemplateFile('order_details.pt') - - def __call__(self): - self.request.set('disable_border', 1) - self.order_id = int(self.request.get('order_id')) - - # use all fields - fields = self.order_fields() - - self.order, sort = self._get_order_data( - self.order_id, - fields, - ) - return self.template() diff --git a/pcommerce/core/browser/portlets/__init__.py b/pcommerce/core/browser/portlets/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/browser/portlets/cart.pt b/pcommerce/core/browser/portlets/cart.pt deleted file mode 100644 index 49f95b1..0000000 --- a/pcommerce/core/browser/portlets/cart.pt +++ /dev/null @@ -1,30 +0,0 @@ -
    - -
    - - Your shopping cart - -
    - -
    -
    -
    No of articles:
    -
    6
    -
    Total CHF:
    -
    120.00
    -
    -
    - -
    - - Check out - -
    -
    diff --git a/pcommerce/core/browser/portlets/cart.py b/pcommerce/core/browser/portlets/cart.py deleted file mode 100644 index 1c3b2a1..0000000 --- a/pcommerce/core/browser/portlets/cart.py +++ /dev/null @@ -1,52 +0,0 @@ -from zope.interface import implements -from zope.component import getMultiAdapter - -from plone.portlets.interfaces import IPortletDataProvider -from plone.app.portlets.portlets import base - -from Products.CMFCore.utils import getToolByName - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.currency import CurrencyAware -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.config import CheckOut -from pcommerce.core.interfaces import IShoppingCart - -class IShoppingCartPortlet(IPortletDataProvider): - """A portlet which renders a users shopping cart - """ - -class Assignment(base.Assignment): - implements(IShoppingCartPortlet) - - title = _(u'Shopping cart') - -class Renderer(base.Renderer): - - def update(self): - self.cart = IShoppingCart(self.context) - - @property - def portal_url(self): - portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') - return portal_state.portal_url() - - @property - def size(self): - return self.cart.amount() - - @property - def price(self): - return CurrencyAware(self.cart.getPrice()) - - @property - def checkout(self): - return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) - - render = ViewPageTemplateFile('cart.pt') - -class AddForm(base.NullAddForm): - - def create(self): - return Assignment() diff --git a/pcommerce/core/browser/portlets/configure.zcml b/pcommerce/core/browser/portlets/configure.zcml deleted file mode 100644 index fde64bf..0000000 --- a/pcommerce/core/browser/portlets/configure.zcml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/browser/prices.pt b/pcommerce/core/browser/prices.pt deleted file mode 100644 index c44a1f0..0000000 --- a/pcommerce/core/browser/prices.pt +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - -
    - - - Add price - - -

    - Additional prices -

    - -
    -
    Info
    -
    - You are currently looking at the prices of a variation of the product - Product title. -
    -
    - -

    - This product has no additional prices. To add a price press the - 'add' button or paste content from another location. -

    - -
    - - - - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      Price  Modified  State   
    - - - - - - - - CHF 100.00 - - expired - - 08/19/2001 03:01 AM - - -   - - - - Edit - - - - Sharing -
    - - - - -
    - -
    -
    - - diff --git a/pcommerce/core/browser/prices.py b/pcommerce/core/browser/prices.py deleted file mode 100644 index 18dd5b5..0000000 --- a/pcommerce/core/browser/prices.py +++ /dev/null @@ -1,58 +0,0 @@ -from zope.component import getMultiAdapter -from zope.interface import implements - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from Products.CMFCore.utils import getToolByName - -from plone.memoize.instance import memoize -from plone.app.content.browser.interfaces import IFolderContentsView -from plone.app.content.browser.foldercontents import FolderContentsTable - -from pcommerce.core.currency import CurrencyAware -from pcommerce.core.interfaces import IPrice -from pcommerce.core.browser.product import Product - -class Prices(Product, FolderContentsTable): - """management view of all prices - """ - implements(IFolderContentsView) - - template = ViewPageTemplateFile('prices.pt') - - def __call__(self): - if self.request.get('prices', None): - prices = self.context.objectIds() - for price in self.request.get('prices', []): - if not isinstance(price, str) and price.id in prices: - self.context[price.id].setPrice(price.price) - self.context[price.id].reindexObject() - return self.template() - - @property - @memoize - def items(self): - catalog = getToolByName(self.context, 'portal_catalog') - plone_view = getMultiAdapter((self.context, self.request), name=u'plone') - utils = getToolByName(self.context, 'plone_utils') - wftool = getToolByName(self.context, 'portal_workflow') - results = catalog(object_provides=IPrice.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), 'depth': 1}) - prices = [] - odd = True - for price in results: - prices.append({'uid': price.UID, - 'id': price.getId, - 'modified': plone_view.toLocalizedTime(price.ModificationDate, long_format=1), - 'state_title': wftool.getTitleForStateOnType(price.review_state, price.portal_type), - 'state_class': 'state-' + utils.normalizeString(price.review_state), - 'is_expired': self.context.isExpired(price), - 'title_or_id': price.pretty_title_or_id(), - 'table_row_class': odd and 'odd' or 'even', - 'raw_price': price.getPrice, - 'price': CurrencyAware(price.getPrice), - 'path': price.getPath, - 'relative_url': price.getURL(relative=True), - 'url': {'edit': '%s/edit' % price.getURL(), - 'sharing': '%s/@@sharing' % price.getURL()}}) - odd = not odd - return prices diff --git a/pcommerce/core/browser/product.pt b/pcommerce/core/browser/product.pt deleted file mode 100644 index 393e5a0..0000000 --- a/pcommerce/core/browser/product.pt +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - -
    - -

    - Title -

    - -
    - -
    - Description -
    - -
    - -
    - -
    - - - - - - \ No newline at end of file diff --git a/pcommerce/core/browser/product.py b/pcommerce/core/browser/product.py deleted file mode 100644 index 1dce9d9..0000000 --- a/pcommerce/core/browser/product.py +++ /dev/null @@ -1,155 +0,0 @@ -from Acquisition import aq_inner, aq_parent - -from Products.Five.browser import BrowserView -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from Products.CMFCore.utils import getToolByName - -from plone.memoize.instance import memoize - -from pcommerce.core.interfaces import IVariation, IPrice, IPricing, IImaging, ITaxes -from pcommerce.core.currency import CurrencyAware - -class Product(BrowserView): - """view of a product - """ - - template = ViewPageTemplateFile('product.pt') - - def __call__(self): - return self.template() - - @memoize - def title(self): - if IVariation.providedBy(self.context): - return '%s (%s: %s)' % (self.product.Title().decode('utf-8'), self.context.getType().decode('utf-8'), self.context.Title().decode('utf-8')) - return self.context.Title() - - @property - @memoize - def description(self): - return self.context.Description() or self.product.Description() - - @property - @memoize - def text(self): - return self.context.getText() or self.product.getText() - - @property - @memoize - def image(self): - props = getToolByName(self.context, 'portal_properties').pcommerce_properties - width = int(props.getProperty('thumb_width_detail', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - context = None - if self.context.getImage(): - context = self.context - elif self.product.getImage(): - context = self.product - if context is None: - return None - return {'caption': context.getImageCaption(), - 'thumb': '%s/%s' % (context.absolute_url(), width), - 'url': '%s/image_preview' % context.absolute_url()} - - @property - @memoize - def images(self): - images = [] - odd = False - i = 0 - - context = None - - if self.context.getImage(): - """ the variation have a image - """ - image = self.image - if image: - image['parity'] = 'odd' - images.append(image) - odd = True - i = 1 - context = self.context - elif not IImaging(self.context).getImages(): - """ the variation have not a image and not images in the content - """ - image = self.image - if image: - image['parity'] = 'odd' - images.append(image) - odd = True - i = 1 - context = self.product - else: - """ the variation have not a image but a images in the content - """ - context = self.context - - props = getToolByName(self.context, 'portal_properties').pcommerce_properties - width = int(props.getProperty('thumb_width_detail', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - - for image_raw in IImaging(context).getImages(): - image = {'url': '%s/image_preview' % (image_raw.getURL()), - 'thumb': '%s/%s' % (image_raw.getURL(), width), - 'caption': image_raw.Title - } - odd = not odd - if odd: - image['parity'] = 'odd' - else: - image['parity'] = 'even' - images.append(image) - i += 1 - - return images - - @property - @memoize - def product(self): - context = aq_inner(self.context) - if IVariation.providedBy(context): - return aq_parent(context) - return self.context - - @property - def price(self): - if IVariation.providedBy(self.context): - return CurrencyAware(IPricing(self.product).getPrice([aq_inner(self.context),])) - return CurrencyAware(IPricing(self.product).getPrice()) - - @property - def base_price(self): - if IVariation.providedBy(self.context): - return CurrencyAware(IPricing(self.product).getBasePrice([aq_inner(self.context),])) - return CurrencyAware(IPricing(self.product).getBasePrice()) - - @property - @memoize - def offer(self): - return self.price.getValue() < self.base_price.getValue() - - @property - def variations(self): - catalog = getToolByName(self.context, 'portal_catalog') - results = catalog(object_provides=IVariation.__identifier__, path={'query': '/'.join(self.product.getPhysicalPath())}) - variations = {} - for variation in results: - if not variations.has_key(variation.getType): - variations[variation.getType] = [] - if not variation.getAddPrice: - price_adapter = IPricing(variation.getObject()) - variations[variation.getType].append({ - 'uid': variation.UID, - 'name': variation.Title, - 'price': CurrencyAware(IPricing(self.product).getPrice([variation.getObject()])), - 'price_raw': IPricing(self.product).getPrice([variation.getObject()]), - 'base_price': CurrencyAware(variation.getAddPrice and self.base_price.getValue() + float(variation.getPrice) or price_adapter.getBasePrice()), - 'base_price_raw':variation.getAddPrice and self.base_price.getValue() + float(variation.getPrice) or price_adapter.getBasePrice(), - 'add_price': variation.getAddPrice and CurrencyAware(float(variation.getPrice)) or None, - 'add_price_raw': variation.getAddPrice and float(variation.getPrice) or None, }) - - - return [{'name': type[0], - 'variations': type[1]} for type in variations.items()] diff --git a/pcommerce/core/browser/variation.pt b/pcommerce/core/browser/variation.pt deleted file mode 100644 index 25d422e..0000000 --- a/pcommerce/core/browser/variation.pt +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - -
    - -

    - Title -

    - -
    -
    Info
    -
    - You are currently looking at a variation of the product - Product title. -
    -
    - -
    - -
    - Description -
    - -
    - -
    - -
    - - - - - - \ No newline at end of file diff --git a/pcommerce/core/browser/variation.py b/pcommerce/core/browser/variation.py deleted file mode 100644 index 79555eb..0000000 --- a/pcommerce/core/browser/variation.py +++ /dev/null @@ -1,8 +0,0 @@ -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.browser.product import Product - -class Variation(Product): - """view of a variation - """ - template = ViewPageTemplateFile('variation.pt') diff --git a/pcommerce/core/browser/variations.pt b/pcommerce/core/browser/variations.pt deleted file mode 100644 index f9d7a66..0000000 --- a/pcommerce/core/browser/variations.pt +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - -
    - - - Add variation - - -

    - Variations -

    - -
    -
    - -
    -
    - - - - diff --git a/pcommerce/core/browser/variations.py b/pcommerce/core/browser/variations.py deleted file mode 100644 index 11b6f73..0000000 --- a/pcommerce/core/browser/variations.py +++ /dev/null @@ -1,11 +0,0 @@ -from plone.app.content.browser.foldercontents import FolderContentsView, FolderContentsTable - -from pcommerce.core.interfaces import IVariation - -class Variations(FolderContentsView): - """management view of all variations - """ - - def contents_table(self): - table = FolderContentsTable(self.context, self.request, {'object_provides': IVariation.__identifier__}) - return table.render() \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/__init__.py b/pcommerce/core/browser/viewlets/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/browser/viewlets/buy.pt b/pcommerce/core/browser/viewlets/buy.pt deleted file mode 100644 index db8f6e2..0000000 --- a/pcommerce/core/browser/viewlets/buy.pt +++ /dev/null @@ -1,22 +0,0 @@ -
    -
    - - - - - - - - - -
    -
    diff --git a/pcommerce/core/browser/viewlets/buy.py b/pcommerce/core/browser/viewlets/buy.py deleted file mode 100644 index 3f94e94..0000000 --- a/pcommerce/core/browser/viewlets/buy.py +++ /dev/null @@ -1,46 +0,0 @@ -from zope.component import getMultiAdapter - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -class BuyViewlet(ViewletBase): - index = ViewPageTemplateFile('buy.pt') - - def update(self): - ViewletBase.update(self) - self.product_view = getMultiAdapter((self.context, self.request), name=u'view') - - @property - @memoize - def product(self): - return self.product_view.product - - @property - @memoize - def price(self): - return self.product_view.price - - @property - @memoize - def base_price(self): - return self.product_view.base_price - - @property - @memoize - def variations(self): - types = [] - for type in self.product_view.variations: - variations = [] - for variation in type['variations']: - if self.context.Title() == variation['name']: - variation['selected'] = True - else: - variation['selected'] = False - variations.append(variation) - type['variations'] = variations - types.append(type) - return types - - \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/configure.zcml b/pcommerce/core/browser/viewlets/configure.zcml deleted file mode 100644 index 4b9b92b..0000000 --- a/pcommerce/core/browser/viewlets/configure.zcml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/hot.pt b/pcommerce/core/browser/viewlets/hot.pt deleted file mode 100644 index 0b1edc6..0000000 --- a/pcommerce/core/browser/viewlets/hot.pt +++ /dev/null @@ -1,10 +0,0 @@ -
    -

    - Product highlights -

    -
    - -
    - -
    -
    \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/hot.py b/pcommerce/core/browser/viewlets/hot.py deleted file mode 100644 index fba51c7..0000000 --- a/pcommerce/core/browser/viewlets/hot.py +++ /dev/null @@ -1,54 +0,0 @@ -from zope.component import getMultiAdapter -import random - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.CMFCore.utils import getToolByName - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.interfaces import IPricing, IProduct -from pcommerce.core.currency import CurrencyAware - -class HotViewlet(ViewletBase): - index = ViewPageTemplateFile('hot.pt') - - def products(self): - catalog = getToolByName(self.context, 'portal_catalog') - portal_properties = getToolByName(self.context, 'portal_properties') - use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) - props = portal_properties.pcommerce_properties - columns = int(props.getProperty('hot_columns', 3)) - no = int(props.getProperty('no_hot_products', 6)) - width = int(props.getProperty('thumb_width_hot_products', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - results = list(catalog(object_provides=IProduct.__identifier__, hot=True)) - if not results: - return None - items = [] - i = 0 - while len(items) < no and len(results): - item = results.pop(random.randrange(len(results))) - object = item.getObject() - col = i % columns + 1 - i += 1 - adapter = IPricing(object) - image = None - if object.getImage(): - image = {'caption': object.getImageCaption(), - 'thumb': '%s/%s' % (item.getURL(), width)} - url = item.getURL() - if item.portal_type in use_view_action: - url += '/view' - item = {'uid': item.UID, - 'class': 'col%s' % col, - 'title': item.Title, - 'description': item.Description, - 'price': CurrencyAware(adapter.getPrice()), - 'base_price': CurrencyAware(adapter.getBasePrice()), - 'offer': adapter.getPrice() < adapter.getBasePrice(), - 'image': image, - 'url': url} - items.append(item) - return items \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/info.pt b/pcommerce/core/browser/viewlets/info.pt deleted file mode 100644 index 6c6edd7..0000000 --- a/pcommerce/core/browser/viewlets/info.pt +++ /dev/null @@ -1,19 +0,0 @@ -
    - -
    - - - - -
    -
    - -
    - -
    -
    \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/info.py b/pcommerce/core/browser/viewlets/info.py deleted file mode 100644 index 0b03bf2..0000000 --- a/pcommerce/core/browser/viewlets/info.py +++ /dev/null @@ -1,47 +0,0 @@ -from zope.component import getMultiAdapter - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -class InfoViewlet(ViewletBase): - index = ViewPageTemplateFile('info.pt') - - def update(self): - self.product_view = getMultiAdapter((self.context, self.request), name=u'view') - - @property - @memoize - def product(self): - return self.product_view.product - - @property - @memoize - def image(self): - return self.product_view.image - - @property - @memoize - def images(self): - return self.product_view.images - - @property - @memoize - def price(self): - return self.product_view.price - - @property - @memoize - def base_price(self): - return self.product_view.base_price - - @property - @memoize - def offer(self): - return self.product_view.offer - - @property - @memoize - def variations(self): - return self.product_view.variations \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/new.pt b/pcommerce/core/browser/viewlets/new.pt deleted file mode 100644 index ca6ce39..0000000 --- a/pcommerce/core/browser/viewlets/new.pt +++ /dev/null @@ -1,10 +0,0 @@ -
    -

    - New products in our shop -

    -
    - -
    - -
    -
    \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/new.py b/pcommerce/core/browser/viewlets/new.py deleted file mode 100644 index 9e052a2..0000000 --- a/pcommerce/core/browser/viewlets/new.py +++ /dev/null @@ -1,54 +0,0 @@ -import random -from zope.component import getMultiAdapter - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.CMFCore.utils import getToolByName - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.interfaces import IPricing, IProduct -from pcommerce.core.currency import CurrencyAware - -class NewViewlet(ViewletBase): - index = ViewPageTemplateFile('new.pt') - - def products(self): - catalog = getToolByName(self.context, 'portal_catalog') - portal_properties = getToolByName(self.context, 'portal_properties') - use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) - props = portal_properties.pcommerce_properties - columns = int(props.getProperty('new_columns', 2)) - no = int(props.getProperty('no_new_products', 2)) - width = int(props.getProperty('thumb_width_new_products', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - results = list(catalog(object_provides=IProduct.__identifier__, new=True)) - if not results: - return None - items = [] - i = 0 - while len(items) < no and len(results): - item = results.pop(random.randrange(len(results))) - object = item.getObject() - col = i % columns + 1 - i += 1 - adapter = IPricing(object) - image = None - if object.getImage(): - image = {'caption': object.getImageCaption(), - 'thumb': '%s/%s' % (item.getURL(), width)} - url = item.getURL() - if item.portal_type in use_view_action: - url += '/view' - item = {'uid': item.UID, - 'class': 'col%s' % col, - 'title': item.Title, - 'description': item.Description, - 'price': CurrencyAware(adapter.getPrice()), - 'base_price': CurrencyAware(adapter.getBasePrice()), - 'offer': adapter.getPrice() < adapter.getBasePrice(), - 'image': image, - 'url': url} - items.append(item) - return items \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/processor.py b/pcommerce/core/browser/viewlets/processor.py deleted file mode 100644 index d1a4c5f..0000000 --- a/pcommerce/core/browser/viewlets/processor.py +++ /dev/null @@ -1,52 +0,0 @@ -from plone.app.layout.viewlets.common import ViewletBase - -from Products.CMFCore.utils import getToolByName - -from Products.statusmessages.interfaces import IStatusMessage - -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.interfaces import IShoppingCart - -class ProcessorViewlet(ViewletBase): - - def update(self): - self.statusmessages = IStatusMessage(self.request) - try: - amount = int(self.request.get('cartAmount', 1)) - except: - self.statusmessages.addStatusMessage(_(u'Please specify an amount'), 'error') - return - - self.added = self.removed = 0 - adapter = IShoppingCart(self.context) - - if self.request.get('cartAdd', None): - self.added += adapter.add(self.request.get('cartAdd', None), amount) - - elif self.request.get('cartVariation', None): - self.added += adapter.addVariation(self.request.get('cartVariation', None), amount) - if not self.added: - self.statusmessages.addStatusMessage(_(u'Please select a variation'), 'error') - - elif self.request.get('cartRemove', None): - self.removed -= adapter.remove(self.request.get('cartRemove', None), self.request.get('cartRemoveAmount', None)) - - elif self.request.get('cartEdit', None): - a, r = adapter.edit(self.request.get('cartEdit', None)) - self.added += a - self.removed += r - - self.addStatusMessages() - - def index(self): - return '' - - def addStatusMessages(self): - if self.added > 1: - self.statusmessages.addStatusMessage(_(u'Added ${count} items to cart', mapping={'count': self.added}), 'info') - elif self.added == 1: - self.statusmessages.addStatusMessage(_(u'Added item to cart'), 'info') - if self.removed > 1: - self.statusmessages.addStatusMessage(_(u'Removed ${count} items from cart', mapping={'count': self.removed}), 'info') - elif self.removed == 1: - self.statusmessages.addStatusMessage(_(u'Removed item from cart'), 'info') diff --git a/pcommerce/core/browser/viewlets/related.pt b/pcommerce/core/browser/viewlets/related.pt deleted file mode 100644 index fb8032c..0000000 --- a/pcommerce/core/browser/viewlets/related.pt +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/related.py b/pcommerce/core/browser/viewlets/related.py deleted file mode 100644 index b7965b0..0000000 --- a/pcommerce/core/browser/viewlets/related.py +++ /dev/null @@ -1,56 +0,0 @@ -from zope.component import getMultiAdapter - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.CMFCore.utils import getToolByName - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile - -from pcommerce.core.interfaces import IPricing, IProduct -from pcommerce.core.currency import CurrencyAware - -class RelatedViewlet(ViewletBase): - index = ViewPageTemplateFile('related.pt') - - def update(self): - self.view = getMultiAdapter((self.context, self.request), name=u'view') - - @property - @memoize - def product(self): - return self.view.product - - @property - @memoize - def related_items(self): - portal_properties = getToolByName(self.context, 'portal_properties') - use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) - props = portal_properties.pcommerce_properties - columns = int(props.getProperty('columns', 3)) - width = int(props.getProperty('thumb_width', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - items = [] - i = 0 - for item in self.product.getRelatedItems(): - if IProduct.providedBy(item): - col = i % columns + 1 - i += 1 - adapter = IPricing(item) - image = None - if item.getImage(): - image = {'caption': item.getImageCaption(), - 'thumb': '%s/%s' % (item.absolute_url(), width)} - url = item.getURL() - if item.portal_type in use_view_action: - url += '/view' - items.append({'uid': item.UID(), - 'class': 'col%s' % col, - 'title': item.Title(), - 'description': item.Description(), - 'price': CurrencyAware(adapter.getPrice()), - 'base_price': CurrencyAware(adapter.getBasePrice()), - 'offer': adapter.getPrice() < adapter.getBasePrice(), - 'image': image, - 'url': url}) - return items \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/variation.pt b/pcommerce/core/browser/viewlets/variation.pt deleted file mode 100644 index f642fd4..0000000 --- a/pcommerce/core/browser/viewlets/variation.pt +++ /dev/null @@ -1,10 +0,0 @@ -
    -

    - Product variations -

    -
    - -
    - -
    -
    \ No newline at end of file diff --git a/pcommerce/core/browser/viewlets/variation.py b/pcommerce/core/browser/viewlets/variation.py deleted file mode 100644 index ed1a4f1..0000000 --- a/pcommerce/core/browser/viewlets/variation.py +++ /dev/null @@ -1,53 +0,0 @@ -from zope.component import getMultiAdapter - -from plone.memoize.instance import memoize -from plone.app.layout.viewlets.common import ViewletBase - -from Products.CMFCore.utils import getToolByName - -from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile -from pcommerce.core.interfaces import IPricing, IProduct, IVariation -from pcommerce.core.currency import CurrencyAware - -class VariationViewlet(ViewletBase): - index = ViewPageTemplateFile('variation.pt') - - @property - @memoize - def product(self): - return self.view.product - - def variation_items(self): - props = getToolByName(self.context, 'portal_properties').pcommerce_properties - columns = int(props.getProperty('columns', 3)) - width = int(props.getProperty('thumb_width', 0)) - width = width and 'image/thumb?width=%s' % width or 'image_thumb' - items = [] - i = 0 - - catalog = getToolByName(self.product, 'portal_catalog') - variations = catalog(object_provides=IVariation.__identifier__, path={'query': '/'.join(self.product.getPhysicalPath())}) - - for variation in variations: - col = i % columns + 1 - i += 1 - - variation = variation.getObject() - adapter = IPricing(self.product) - - if variation.UID() != self.context.UID(): - image = None - if variation.getImage(): - image = {'caption': variation.getImageCaption(), - 'thumb': '%s/%s' % (variation.absolute_url(), width)} - - items.append({'uid': variation.UID(), - 'class': 'col%s' % col, - 'title': '%s: %s' % (variation.getType(), variation.Title()), - 'description': variation.Description() or self.product.Description(), - 'price': CurrencyAware(adapter.getPrice([variation, ])), - 'base_price': CurrencyAware(adapter.getBasePrice()), - 'offer': adapter.getPrice([variation, ]) < adapter.getBasePrice(), - 'image': image, - 'url': variation.absolute_url()}) - return items diff --git a/pcommerce/core/cart.py b/pcommerce/core/cart.py deleted file mode 100644 index 554544f..0000000 --- a/pcommerce/core/cart.py +++ /dev/null @@ -1,256 +0,0 @@ -from zope.interface import implements, Interface -from zope.component import adapts - -from Acquisition import aq_parent -from Products.CMFCore.utils import getToolByName - -from pcommerce.core.currency import CurrencyAware -from pcommerce.core import interfaces - -SESSION_KEY = 'pcommerce.core.cart' - - -class Cart(object): - """ - """ - _items = {} - - def __len__(self): - return len(self._items) - - def __getitem__(self, key): - return self._items[key] - - def __setitem__(self, key, value): - if key: - self._items[key] = value - self._save() - - def __contains__(self, key): - return key in self._items - - def has_key(self, key): - return key in self._items - - def items(self): - return self._items.items() - - -class ShoppingCart(Cart): - """ An adapter to handle a shopping cart - - the adapter supports the following standard python methods: - - len(ShoppingCart) - ShoppingCart.has_key(key) - ShoppingCart.items() - ShoppingCart[key] - ShoppingCart[key] = value - del(ShoppingCart[key]) - """ - implements(interfaces.IShoppingCart) - adapts(Interface) - - def __init__(self, context): - self.context = context - # avoid creating a session implicitly - session = self.context.session_data_manager.getSessionData(create=0) - self._items = session and session.get(SESSION_KEY, {}) or {} - - def __delitem__(self, key): - del(self._items[key]) - self._save() - - def amount(self): - """ returns amount of products in the cart - """ - size = 0 - for uid, amount in self.items(): - size += amount - return size - - def getPrice(self): - """ returns the total price of all products in the cart - """ - price = 0.0 - products = self.getProducts() - for product in products: - price += product['price_total_raw'] - return price - - def getProducts(self): - """ returns list of products currently in the cart - """ - catalog = getToolByName(self.context, 'uid_catalog') - portal_properties = getToolByName(self.context, 'portal_properties') - use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) - - products = [] - for uid, amount in self.items(): - results = [product.getObject() for product in catalog( - object_provides=interfaces.IProduct.__identifier__, UID=uid)] - if results: - variations = [] - variations_raw = [] - product = None - for result in results: - if interfaces.IVariation.providedBy(result): - variations_raw.append(result) - variation = {'type': result.getType(), - 'name': result.Title(), - 'no': result.getNo(), - 'add_price': None, - 'add_price_raw': None, - 'uid': result.UID(), - 'object': result} - if result.getAddPrice(): - variation['add_price_raw'] =\ - float(result.getPrice()) - variation['add_price'] =\ - CurrencyAware(result.getPrice()) - variations.append(variation) - if not product: - product = aq_parent(result) - else: - product = result - url = product.absolute_url() - if product.portal_type in use_view_action: - product_url = url + '/view' - else: - product_url = url - price = interfaces.IPricing(product).getPrice(variations_raw) - products.append({'title': product.Title(), - 'no': product.getNo(), - 'description': product.Description(), - 'price': CurrencyAware(price), - 'price_raw': price, - 'price_total': CurrencyAware(price * amount), - 'price_total_raw': price * amount, - 'uid': product.UID(), - 'amount': amount, - 'url': product_url, - 'image_url': url, - 'variations': variations, - 'object': product - }) - return products - - def addVariation(self, item, amount=1): - """ adds a variation of a product to the cart - - possible values of item: - - a uid - - a list of uids (combination of multiple variations) - """ - uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( - 'UID') - if not isinstance(item, basestring): - item.sort() - for i in item: - if not i in uids: - return 0 - item = tuple(item) - elif not item in uids: - return 0 - - return self._addItem({'uid': item, - 'amount': int(amount)}) - - def add(self, items, amount=1): - """ adds products to the cart - - possible values of items: - - a uid - - list of uids (multiple products) - - list of dicts with 'uid' and 'amount' key - (multiple products with different amounts) - """ - added = 0 - if isinstance(items, basestring): - items = ({'uid': items, - 'amount': int(amount)},) - uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( - 'UID') - for item in items: - if isinstance(item, basestring): - item = {'uid': item, - 'amount': int(amount)} - if item['uid'] in uids: - added += self._addItem(item) - return added - - def remove(self, items, amount=None): - """ removes products from the cart - - possible values of items: - - a uid - - list of uids (multiple products) - - list of dicts with 'uid' and 'amount' keys - (multiple products with different amounts) - """ - removed = 0 - if isinstance(items, basestring): - items = ({'uid': items, - 'amount': amount},) - for item in items: - if isinstance(item, basestring): - item = {'uid': item, - 'amount': amount} - if item['uid'] in self: - if not item['amount'] or int(item['amount']) is 0 or \ - int(item['amount']) >= self[item['uid']]: - removed += self[item['uid']] - del self[item['uid']] - else: - removed += int(item['amount']) - self[item['uid']] = self[item['uid']] - int(item['amount']) - return removed - - def edit(self, items): - """ edits the cart - - items has to be a list of dicts with keys 'uid', 'amount' - and 'remove' - """ - added = removed = 0 - uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( - 'UID') - for item in items: - if 'variation' in item: - item['variation'].sort() - if item['uid'] in uids and int(item['amount']) > 0 and \ - (not 'remove' in item or not item['remove']): - if 'variation' in item and item['variation']: - item = {'uid': tuple(item['variation']), - 'amount': item['amount']} - if item['uid'] in self: - removed += self[item['uid']] > int(item['amount']) \ - and self[item['uid']] - int(item['amount']) or 0 - added += self[item['uid']] < int(item['amount']) \ - and int(item['amount']) - self[item['uid']] or 0 - else: - added += int(item['amount']) - self[item['uid']] = int(item['amount']) - if ('remove' in item and item['remove']) or \ - int(item['amount']) is 0: - uid = 'variation' in item and tuple(item['variation']) or\ - item['uid'] - removed += self.remove([{'uid': uid, - 'amount': None}]) - return added, removed - - def clear(self): - """ clears the cart - """ - self._items = {} - self._save() - - def _addItem(self, item): - added = item['amount'] - if item['uid'] in self: - item['amount'] += self[item['uid']] - self[item['uid']] = item['amount'] - return added - - def _save(self): - self.context.REQUEST.SESSION.set(SESSION_KEY, self._items) diff --git a/pcommerce/core/charge.py b/pcommerce/core/charge.py deleted file mode 100644 index bc3aec1..0000000 --- a/pcommerce/core/charge.py +++ /dev/null @@ -1,17 +0,0 @@ -from persistent import Persistent - -from zope.interface import implements - -from pcommerce.core.interfaces import IChargeData - -class ChargeData(Persistent): - """ Base implementation of a charge data object - """ - implements(IChargeData) - - title = u'' - price = 0.0 - - def __init__(self, title, price): - self.title = title - self.price = price \ No newline at end of file diff --git a/pcommerce/core/config.py b/pcommerce/core/config.py deleted file mode 100644 index 897c7a4..0000000 --- a/pcommerce/core/config.py +++ /dev/null @@ -1,46 +0,0 @@ -from AccessControl import ModuleSecurityInfo -from Products.CMFCore.permissions import setDefaultRoles - -security = ModuleSecurityInfo('pcommerce.core.config') - -security.declarePublic('AddProduct') -AddProduct = 'PCommerce: Add Product' -setDefaultRoles(AddProduct, ('Manager','Contributer','Owner',)) - -security.declarePublic('AddVariation') -AddVariation = 'PCommerce: Add Variation' -setDefaultRoles(AddVariation, ('Manager','Contributer','Owner',)) - -security.declarePublic('AddImage') -AddVariation = 'PCommerce: Add Image' -setDefaultRoles(AddVariation, ('Manager','Contributer','Owner',)) - -security.declarePublic('AddPrice') -AddPrice = 'PCommerce: Add Price' -setDefaultRoles(AddPrice, ('Manager','Contributer','Owner',)) - -security.declarePublic('AddToCart') -AddToCart = 'PCommerce: Add to Cart' -setDefaultRoles(AddToCart, ('Anonymous', 'Authenticated',)) - -security.declarePublic('CheckOut') -CheckOut = 'PCommerce: Check out' -setDefaultRoles(CheckOut, ('Authenticated',)) - -security.declarePublic('ManageOrders') -ManageOrders = 'PCommerce: Manage Orders' -setDefaultRoles(ManageOrders, ('Manager',)) - -permissions = {'Product': AddProduct, - 'Variation': AddVariation, - 'Price': AddPrice} - -INITIALIZED = 1 -SENT = 2 -PROCESSED = 3 -FAILED = 4 -CANCELED = 5 - -PROJECTNAME = "pcommerce.core" - -product_globals = globals() diff --git a/pcommerce/core/configure.zcml b/pcommerce/core/configure.zcml deleted file mode 100644 index 25df042..0000000 --- a/pcommerce/core/configure.zcml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pcommerce/core/content/__init__.py b/pcommerce/core/content/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/content/price.py b/pcommerce/core/content/price.py deleted file mode 100644 index cca06bd..0000000 --- a/pcommerce/core/content/price.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Price content type -""" - -from AccessControl import ClassSecurityInfo - -from zope.interface import implements - -from Products.Archetypes.public import * - -from pcommerce.core.interfaces import IPrice -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.config import PROJECTNAME - -PriceSchema = BaseContent.schema.copy() + Schema(( - - FixedPointField( - name='price', - required=1, - languageIndependent=True, - widget=DecimalWidget( - label=_(u'Price'), - ) - ), - -)) - -for field in ('description', 'creators','allowDiscussion','contributors','location','subject','language','rights','title',): - if PriceSchema.has_key(field): - PriceSchema[field].widget.visible = 0 - -PriceSchema['title'].required = False - -class Price(BaseContent): - """ A Price - """ - implements(IPrice) - - portal_type = meta_type = "Price" - schema = PriceSchema - _at_rename_after_creation = False - -registerType(Price, PROJECTNAME) \ No newline at end of file diff --git a/pcommerce/core/content/product.py b/pcommerce/core/content/product.py deleted file mode 100644 index 7aee01f..0000000 --- a/pcommerce/core/content/product.py +++ /dev/null @@ -1,136 +0,0 @@ -"""Product content-type -""" - -from AccessControl import ClassSecurityInfo - -from zope.interface import implements - -try: - from Products.LinguaPlone.public import * -except ImportError: - # No multilingual support - from Products.Archetypes.public import * - -from Products.validation import V_REQUIRED - -from Products.CMFCore.permissions import View - -from Products.ATContentTypes.content.document import ATDocumentBase, ATDocumentSchema - -from pcommerce.core.interfaces import IProduct -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.config import PROJECTNAME - -from Products.CMFPlone.interfaces import INonStructuralFolder -from Products.CMFPlone import PloneMessageFactory as _p - -from zope.schema.interfaces import IVocabularyFactory - -ProductSchema = ATDocumentSchema.copy() + Schema(( - - StringField( - name='no', - searchable=1, - widget=StringWidget( - label=_('No'), - ) - ), - - FixedPointField( - name='price', - languageIndependent=True, - widget=DecimalWidget( - label=_(u'Price'), - ) - ), - - BooleanField( - name='new', - languageIndependent=True, - widget=BooleanWidget( - label=_(u'New product'), - ) - ), - - BooleanField( - name='hot', - languageIndependent=True, - widget=BooleanWidget( - label=_(u'Hot product'), - ) - ), - - LinesField( - name='shipments', - required = True, - multiValued = True, - widget = MultiSelectionWidget(label = _(u'label_shipment_methods', default=u'Shipment methods'), - description = _(u'description_shipment_methods', default=u'Shipment methods for this product'), - format = 'checkbox', - ), - vocabulary_factory = u"pcommerce.core.vocabulary.shipments" - ), - - ImageField( - name='image', - languageIndependent=True, - swallowResizeExceptions=True, - max_size='no', - sizes={'large' : (768, 768), - 'preview' : (400, 400), - 'mini' : (200, 200), - 'thumb' : (128, 128), - 'tile' : (64, 64), - 'icon' : (32, 32), - 'listing' : (16, 16), - }, - validators=(('isNonEmptyFile', V_REQUIRED), - ('checkImageMaxSize', V_REQUIRED),), - widget=ImageWidget(label= _p(u'label_news_image', default=u'Image'), - show_content_type = False,), - ), - - StringField( - name='imageCaption', - required = False, - searchable = True, - widget = StringWidget(description = '', - label = _p(u'label_image_caption', default=u'Image Caption'), - size = 40) - ), - -)) - -for field in ('creators','contributors','location','subject','language','rights','presentation', 'tableContents',): - if ProductSchema.has_key(field): - ProductSchema[field].widget.visible = 0 - -ProductSchema['excludeFromNav'].default = 1 -ProductSchema.changeSchemataForField('relatedItems', 'default') -ProductSchema.moveField('no', after='title') -ProductSchema.moveField('price', after='no') -ProductSchema.moveField('hot', after='description') -ProductSchema.moveField('new', after='hot') -ProductSchema.moveField('shipments', after='new') -ProductSchema.moveField('image', after='shipments') -ProductSchema.moveField('imageCaption', after='image') - -class Product(OrderedBaseFolder, ATDocumentBase): - """ A product - """ - implements(IProduct, INonStructuralFolder) - - portal_type = meta_type = "Product" - schema = ProductSchema - security = ClassSecurityInfo() - _at_rename_after_creation = True - - security.declareProtected(View, 'tag') - def tag(self, **kwargs): - """Generate image tag using the api of the ImageField - """ - if 'title' not in kwargs: - kwargs['title'] = self.getImageCaption() - return self.getField('image').tag(self, **kwargs) - -registerType(Product, PROJECTNAME) \ No newline at end of file diff --git a/pcommerce/core/content/variation.py b/pcommerce/core/content/variation.py deleted file mode 100644 index a686537..0000000 --- a/pcommerce/core/content/variation.py +++ /dev/null @@ -1,62 +0,0 @@ -"""Variation content-type -""" -from zope.interface import implements - -try: - from Products.LinguaPlone.public import * -except ImportError: - # No multilingual support - from Products.Archetypes.public import * - -from Products.SingleKeywordWidget.widget import SingleKeywordWidget - -from pcommerce.core.content.product import Product, ProductSchema - -from pcommerce.core.interfaces import IVariation -from pcommerce.core import PCommerceMessageFactory as _ -from pcommerce.core.config import PROJECTNAME - -VariationSchema = Schema(( - - StringField( - name='type', - required=1, - searchable=True, - widget=SingleKeywordWidget( - label=_(u'Type'), - format='radio', - ) - ), - - BooleanField( - name='addPrice', - languageIndependent=True, - widget=BooleanWidget( - label=_(u'Additional price'), - ) - ), - -)) + ProductSchema.copy() - -VariationSchema['creators'].widget.visible = 0 -VariationSchema.changeSchemataForField('no', 'overrides') -VariationSchema.changeSchemataForField('text', 'overrides') -VariationSchema.changeSchemataForField('relatedItems', 'overrides') -VariationSchema.moveField('title', before='type') -VariationSchema.moveField('addPrice', after='price') -VariationSchema.moveField('effectiveDate', after='imageCaption') -VariationSchema.moveField('expirationDate', after='effectiveDate') - - - -VariationSchema['price'].widget.description = _(u'description_price', default=u'If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination.') - -class Variation(Product): - """ A variation of a product - """ - implements(IVariation) - - portal_type = meta_type = "Variation" - schema = VariationSchema - -registerType(Variation, PROJECTNAME) diff --git a/pcommerce/core/currency.py b/pcommerce/core/currency.py deleted file mode 100644 index ab23b02..0000000 --- a/pcommerce/core/currency.py +++ /dev/null @@ -1,74 +0,0 @@ -from Products.CMFCore.utils import getToolByName -from zope.component import getSiteManager - -try: - from Products.CurrencyUtility.currency import CurrencyAware as CurrencyAwareBase -except: - # CurrencyUtility not available - - import math - - - class CurrencyAwareBase(object): - """helper class to convert values between currencies""" - - value = 0 - context = None - - def __str__(self): - return self.toString() - - def __init__(self, value, currency=None, rounding=None): - self.value = float(value) - if rounding is not None: - self.rounding = rounding - else: - rounding = 0.05 # default value, round to 5 cents - - def getContext(self): - """returns the context""" - if self.context is None: - self.context = getSiteManager() - return self.context - - def getCurrencySymbol(self): - """return the currency registered in site_properties""" - props = getToolByName(self.getContext(), 'portal_properties').site_properties - return props.getProperty('currency', '') - - def getValue(self, currency=None): - """returns the value in the appropriate currency""" - return self.value - - def getRoundedValue(self, currency=None): - """returns the value in the appropriate currency rounded to 0.05""" - value = self.getValue(currency) - factor = 1.0 / self.rounding - return float(int(math.ceil(value*factor)))/factor - - def toString(self, currency=None): - """returns the value in the appropriate currency rounded to 0.05 including the symbol""" - return "%s %0.2f" % (self.getCurrencySymbol(), self.getRoundedValue()) - - def valueToString(self, currency=None): - """returns the value in the appropriate currency rounded to 0.05""" - return "%0.2f" % self.getRoundedValue() - - def safeToString(self, currency=None): - """returns the value in the appropriate currency rounded to 0.05 including the currency-short-name""" - return "%s %0.2f" % (self.getCurrencySymbol(), self.getRoundedValue()) - - -class CurrencyAware(CurrencyAwareBase): - """wrapper around CurrencyAware, so we can use proper rounding""" - - def __init__(self, value, currency=None): - """ - retrieve the rounding from the properties, and - call base init method - """ - context = getSiteManager() - props = getToolByName(context, 'portal_properties').pcommerce_properties - rounding_cents = int(props.getProperty('rounding_cents', 5)) - rounding = rounding_cents * 0.01 - super(CurrencyAware, self).__init__(value, currency, rounding) diff --git a/pcommerce/core/data.py b/pcommerce/core/data.py deleted file mode 100644 index b425f6d..0000000 --- a/pcommerce/core/data.py +++ /dev/null @@ -1,23 +0,0 @@ -from persistent import Persistent - -from zope.interface import implements - -from pcommerce.core.interfaces import IPaymentData, IShipmentData - -class BaseData(Persistent): - pretaxcharge = 0.0 - posttaxcharge = 0.0 - - def __init__(self, id, pretaxcharge=0.0, posttaxcharge=0.0, **kwargs): - self.id = id - self.pretaxcharge = pretaxcharge - self.posttaxcharge = posttaxcharge - for key, value in kwargs.items(): - setattr(self, key, value) - -class PaymentData(BaseData): - implements(IPaymentData) - -class ShipmentData(BaseData): - implements(IShipmentData) - diff --git a/pcommerce/core/events.py b/pcommerce/core/events.py deleted file mode 100644 index 4a96e66..0000000 --- a/pcommerce/core/events.py +++ /dev/null @@ -1,39 +0,0 @@ -from zope.interface import implements - -from pcommerce.core import interfaces - -class OrderEvent(object): - - def __init__(self, registry, order): - self.registry = registry - self.order = order - -class OrderProcessingSuccessfulEvent(OrderEvent): - implements(interfaces.IOrderProcessingSuccessfulEvent) - -class OrderProcessingFailedEvent(OrderEvent): - implements(interfaces.IOrderProcessingFailedEvent) - -class OrderProcessedEvent(OrderEvent): - implements(interfaces.IOrderProcessedEvent) - -class OrderCreatedEvent(OrderEvent): - implements(interfaces.IOrderCreatedEvent) - -class OrderAboutToBeRecreatedEvent(OrderEvent): - implements(interfaces.IOrderAboutToBeRecreatedEvent) - -class OrderRecreatedEvent(OrderEvent): - implements(interfaces.IOrderRecreatedEvent) - -class OrderRecoveredEvent(OrderEvent): - implements(interfaces.IOrderRecoveredEvent) - -class OrderSentEvent(OrderEvent): - implements(interfaces.IOrderSentEvent) - -class OrderFailedEvent(OrderEvent): - implements(interfaces.IOrderFailedEvent) - -class OrderCanceledEvent(OrderEvent): - implements(interfaces.IOrderCanceledEvent) diff --git a/pcommerce/core/interfaces.py b/pcommerce/core/interfaces.py deleted file mode 100644 index df99e2c..0000000 --- a/pcommerce/core/interfaces.py +++ /dev/null @@ -1,488 +0,0 @@ -from zope.interface import Interface, Attribute -from zope.publisher.interfaces.browser import IBrowserView - -class IProduct(Interface): - """ A product - """ - -class IVariation(IProduct): - """ A variation of a product - """ - -class IShop(Interface): - """ shop view - """ - -class IShopFolder(Interface): - """ shop folder view - """ - -class IPrice(Interface): - """ A price - """ - -class IShoppingCart(Interface): - """ An adapter to handle a shopping cart - - the adapter supports the following stanard python methods: - - len(ShoppingCart) - ShoppingCart.has_key(key) - ShoppingCart.items() - ShoppingCart[key] - ShoppingCart[key] = value - del ShoppingCart[key] - """ - - def getProducts(): - """ returns a list of products currently in the cart - """ - - def getPrice(): - """ returns the total price of all products in the cart - """ - - def addVariation(item, amount=1): - """ adds a variation of a product to the cart - - possible values of item: - - a uid - - a list of uids (combination of multiple variations) - """ - - def add(items, amount=1): - """ adds products to the cart - - possible values of items: - - a uid - - list of uids (multiple products) - - list of dicts with 'uid' and 'amount' key (multiple products with different amounts) - """ - - def remove(items, amount=None): - """ removes products from the cart - - possible values of items: - - a uid - - list of uids (multiple products) - - list of dicts with 'uid' and 'amount' key (multiple products with different amounts) - """ - - def edit(items): - """ edits the cart - - items has to be a list of dicts with keys 'uid', 'amount' and 'remove' - """ - - def clear(): - """ clears the cart - """ - -class IOrderRegistry(Interface): - """ An adapter to handle the order registry - - the adapter supports the following standard python methods: - - len(OrderRegistry) - OrderRegistry.has_key(key) - OrderRegistry.items() - OrderRegistry[key] - OrderRegistry[key] = value - """ - - def getOrders(): - """ returns a list of orders - """ - - def getOrder(orderid): - """ returns a order by its id - """ - - def create(order): - """ generates an order from the cart - """ - - def recover(orderid): - """ recover an order from the registry - """ - - def send(orderid, lang=None): - """ sends an order - """ - - def process(orderid): - """ process an order - """ - - def cancel(orderid): - """ cancel an order - """ - - def fail(orderid): - """ fail an order - """ - -class IAddress(Interface): - """ An address - """ - - salutation = Attribute("""string""") - - name = Attribute("""string""") - - address1 = Attribute("""string""") - - address2 = Attribute("""string""") - - zip = Attribute("""string""") - - city = Attribute("""string""") - - country = Attribute("""string""") - - zone = Attribute("""string""") - - email = Attribute("""string""") - - phone = Attribute("""string""") - - def mailInfo(request, lang=None, customer=False): - """ returns plain text information about the address to be sent by email """ - -class IAddressFactory(Interface): - """ An adapter to validate and create IAddress objects - """ - - def create(tag): - """ Returns a new Address object based on the request - """ - - def validate(tag): - """ Validates the data in the request to match the ones used for an Address - """ - -class IOrder(Interface): - """ An order - """ - - state = Attribute( - """integer: the current state of the order""") - - orderid = Attribute( - """string: the orderid""") - - userid = Attribute( - """string: the userid""") - - products = Attribute( - """list: list of products""") - - date = Attribute( - """time""") - - price = Attribute( - """float: the price""") - - zone = Attribute( - """tuple: (name, (tax, taxname))""") - - currency = Attribute( - """string: the currency""") - - address = Attribute( - """IAddress: customer address""") - - paymentid = Attribute( - """string: name of the payment method""") - - paymentdata = Attribute( - """IPayment: data stored by the payment method""") - - shipmentids = Attribute( - """dict: mapping of shipmentid to product uids""") - - shipmentdata = Attribute( - """dict: mapping of IShipmentData objects to shipmentid""") - - pretaxcharges = Attribute( - """tuple: list of IChargeData objects""") - - posttaxcharges = Attribute( - """tuple: list of IChargeData objects""") - - total = Attribute( - """float: the total price including tax and pre tax shipment prices""") - - subtotal = Attribute( - """float: the total price including pre tax shipment prices""") - - totalincl = Attribute( - """float: the total price including tax and shipment prices""") - - pretaxcharge = Attribute( - """float: pre tax charge""") - - posttaxcharge = Attribute( - """float: post tax charge""") - - zonename = Attribute( - """string: the name of the zone""") - - taxname = Attribute( - """string: the name of the tax""") - - tax = Attribute( - """float: the tax factor""") - - pricetax = Attribute( - """float: the tax price""") - -class IPaymentProcessor(Interface): - """""" - - def processOrder(orderid, paymentid, lang=None): - """ Processes an order """ - -class IOrderEvent(Interface): - """ An event that's fired upon order change. - """ - registry = Attribute(u'The order registry the order is stored in') - order = Attribute(u'The order object') - -class IOrderProcessingSuccessfulEvent(IOrderEvent): - """ An event that's fired if processing an order was successful - """ - -class IOrderProcessingFailedEvent(IOrderEvent): - """ An event that's fired if processing an order failed - """ - -class IOrderProcessedEvent(IOrderEvent): - """ An event fired after a order has been processed - """ - -class IOrderCreatedEvent(IOrderEvent): - """ An event that's fired if an order was created from a cart - """ - -class IOrderAboutToBeRecreatedEvent(IOrderEvent): - """ An event that's fired if an order is about to be recreated from a cart - """ - -class IOrderRecreatedEvent(IOrderEvent): - """ An event that's fired if an order was re created from a cart - """ - -class IOrderRecoveredEvent(IOrderEvent): - """ An event that's fired if an order was recovered - """ - -class IOrderSentEvent(IOrderEvent): - """ An event that's fired if an order was sent - """ - -class IOrderFailedEvent(IOrderEvent): - """ An event that's fired if an order failed - """ - -class IOrderCanceledEvent(IOrderEvent): - """ An event that's fired if an order was canceled - """ - -class IPricing(Interface): - """ An adapter to handle prices of a product - """ - - def getPrice(): - """ The lowest available price - """ - - def getBasePrice(): - """ The base price defined on the product - """ - -class IImaging(Interface): - """ An adapter to handle images of a product - """ - - def getImages(): - """ All Images inside of the Product - """ - -class ITaxes(Interface): - """ An adapter to handle taxes based on zones - - len(Taxes) - Taxes.has_key(key) - Taxes.items() - Taxes[key] - Taxes[key] = value - del Taxes[key] - """ - - def edit(taxes): - """ edits the taxes - - taxes has to be a list of dicts with keys 'zone', 'tax', 'taxname' - """ - -class ICheckoutView(Interface): - """ Checkout view - """ - -class ISteps(Interface): - """ Steps provider - """ - -class IRequiredComponents(Interface): - """ Required components provider - - Components which have to be processed in order to - make an order definite - """ - -class IComponent(IBrowserView): - """ A component for the checkout steps - """ - - dependencies = Attribute(u'Tuple: name of dependencies components') - - def validate(self): - """ validate the form values """ - - def process(self): - """ process of the component """ - - def renders(self): - """ defines whether a component renders or not """ - -class IPaymentRegistry(Interface): - """ An adapter holding registered payment - """ - - def getPayments(): - """ get all registered payment methods """ - -class IShipmentRegistry(Interface): - """ An adapter holding registered shipments - """ - - def getShipments(): - """ get all registered shipment methods """ - -class IPaymentMethod(Interface): - """ A payment method - """ - - title = Attribute( - """unicode: the title of the payment method""") - - decription = Attribute( - """unicode: the description of the payment method""") - - icon = Attribute( - """string: icon resource""") - - logo = Attribute( - """string: logo resource""") - - def verifyPayment(order): - """verify the payment""" - - def mailInfo(order, lang=None, customer=False): - """ returns plain text information about the payment to be sent by email """ - -class IPaymentData(Interface): - """ A payment object to be stored on the order - """ - - paymentid = Attribute( - """ the name of the corresponding payment method """) - - pretaxcharge = Attribute( - """ returns the pre tax charge for this payment """) - - posttaxcharge = Attribute( - """ returns the post tax charge for this payment """) - -class IPaymentView(Interface): - """ A payment view - """ - - def validate(self): - """ validate the form values """ - - def process(self): - """ process of the payment view and return a IPaymentData object """ - - def renders(self): - """ defines whether a payment view renders or not """ - -class IShipmentMethod(Interface): - """ A shipment method - """ - - title = Attribute( - """unicode: the title of the payment method""") - - decription = Attribute( - """unicode: the description of the payment method""") - - icon = Attribute( - """string: icon resource""") - - logo = Attribute( - """string: logo resource""") - - def mailInfo(order, lang=None, customer=False): - """ returns plain text information about the shipment to be sent by email """ - -class IShipmentData(Interface): - """ A shipment object to be stored on the order - """ - - shipmentid = Attribute( - """ the name of the corresponding shipment method """) - - pretaxcharge = Attribute( - """ returns the pre tax charge for this shipment """) - - posttaxcharge = Attribute( - """ returns the post tax charge for this shipment """) - -class IShipmentView(Interface): - """ A shipment view - """ - - def validate(self): - """ validate the form values """ - - def process(self): - """ process of the shipment view and return a IShipmentData object """ - - def renders(self): - """ defines whether a shipment view renders or not """ - -class IPreTaxCharge(Interface): - """ An adapter to provide a pre tax charge - """ - - def process(order): - """ returns an IChargeData object containing the charge """ - -class IPostTaxCharge(Interface): - """ An adapter to provide a post tax charge - """ - - def process(order): - """ returns an IChargeData object containing the charge """ - -class IChargeData(Interface): - """ An additional charge for an order - """ - - title = Attribute( - """unicode: the title of the charge""") - - price = Attribute( - """flaot: the price""") diff --git a/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po b/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po deleted file mode 100644 index 53517b4..0000000 --- a/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po +++ /dev/null @@ -1,770 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: 2007-11-01 10:18+0100\n" -"Last-Translator: Simon Kaeser \n" -"Language-Team: Deutsch \n" -"Language: de\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: pcommerce\n" -"Language-code: de\n" -"Language-name: Deutsch\n" -"Preferred-encodings: utf-8 latin1\n" -"X-is-fallback-for: de-ch de-de de-at de-li de-lu\n" -"X-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" -"X-Poedit-SourceCharset: utf-8\n" - -#. Default: "Add image" -#: browser/images.pt:23 -msgid "Add image" -msgstr "Bild hinzufügen" - -#. Default: "Add price" -#: browser/prices.pt:24 -msgid "Add price" -msgstr "Preis hinzufügen" - -#. Default: "Add variation" -#: browser/variations.pt:22 -msgid "Add variation" -msgstr "Variation hinzufügen" - -#: browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "${count} Artikel dem Warenkorb hinzugefügt" - -#: browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "Artikel dem Warenkorb hinzugefügt" - -#: content/variation.py:35 -msgid "Additional price" -msgstr "Preisaufschlag" - -#. Default: "Additional prices" -#: browser/prices.pt:27 -msgid "Additional prices" -msgstr "Zusätzliche Preise" - -#: steps.py:10 -msgid "Address" -msgstr "Adresse" - -#. Default: "Address 1" -#: browser/address.pt:139 -msgid "Address 1" -msgstr "Adresse 1" - -#. Default: "Address 2" -#: browser/address.pt:166 -msgid "Address 2" -msgstr "Adresse 2" - -#. Default: "Amount" -#: browser/cart.pt:42 -msgid "Amount" -msgstr "Anzahl" - -#. Default: "Billing address" -#: browser/components/address.pt:12 -msgid "Billing address" -msgstr "Rechnungsadresse" - -#: browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "Bestellung abbrechen" - -#. Default: "Check out" -#: browser/cart.pt:34 -msgid "Check out" -msgstr "zur Kasse gehen" - -#. Default: "Company" -#: browser/address.pt:120 -msgid "Company" -msgstr "Firma" - -#. Default: "Confirmation" -#: browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "Bestätigung" - -#: browser/checkout.py:255 -msgid "Continue shopping" -msgstr "Einkauf fortsetzen" - -#. Default: "Country" -#: browser/address.pt:224 -msgid "Country" -msgstr "Land" - -#. Default: "Edit cart" -#: browser/cart.pt:120 -msgid "Edit cart" -msgstr "Warenkorb bearbeiten" - -#. Default: "Email" -#: browser/address.pt:294 -msgid "Email" -msgstr "Email" - -#. Default: "Email address" -#: browser/configlet.pt:116 -msgid "Email address" -msgstr "Emailadresse" - -#. Default: "First name" -#: browser/address.pt:64 -msgid "First name" -msgstr "Vorname" - -#. Default: "GTC" -#: browser/configlet.pt:68 -msgid "GTC" -msgstr "AGB" - -#: content/product.py:59 -msgid "Hot product" -msgstr "Hot Produkt" - -#. Default: "I accept the ${link}" -#: browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "Ich akzeptiere die ${link}" - -#. Default: "Image" -#: browser/images.pt:63 -msgid "Image" -msgstr "Bild" - -#. Default: "Images" -#: browser/images.pt:26 -msgid "Images" -msgstr "Bilder" - -#. Default: "Last name" -#: browser/address.pt:92 -msgid "Last name" -msgstr "Nachname" - -#. Default: "Manage orders" -#: profiles/default/actions.xml -msgid "Manage orders" -msgstr "Bestellungen verwalten" - -#. Default: "Mr." -#: browser/address.pt:46 -msgid "Mr." -msgstr "Herr" - -#. Default: "Mrs. / Ms." -#: browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "Frau" - -#: content/product.py:51 -msgid "New product" -msgstr "Neues Produkt" - -#. Default: "New products in our shop" -#: browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "Neue Produkte im Shop" - -#: browser/checkout.py:258 -msgid "Next step" -msgstr "Nächster Schritt" - -#: browser/orders.py:110 -msgid "No" -msgstr "Artikelnummer" - -#. Default: "No of articles:" -#: browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "Anzahl Artikel:" - -#. Default: "Overview" -#: browser/components/overview.pt:9 -msgid "Overview" -msgstr "Übersicht" - -#. Default: "PCommerce configuration" -#: browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "Einstellungen PCommerce" - -#. Default: "Payment" -#: browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "Zahlungsart" - -#: browser/checkout.py:331 -msgid "Payment canceled" -msgstr "Zahlungsvorgang abgebrochen" - -#: browser/checkout.py:316 -msgid "Payment failed" -msgstr "Zahlungsvorgang fehlgeschlagen" - -#. Default: "Phone" -#: browser/address.pt:322 -msgid "Phone" -msgstr "Telefon" - -#: browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "Bitte geben Sie eine Dezimalzahl ein (z.B. 7.6)" - -#: browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "Bitte geben Sie einen Namen für di Steuer ein" - -#: browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "Bitte geben Sie einen Zonennamen an" - -#: browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "Bitte wählen Sie eine Zahlungsmethode" - -#: browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "Bitte wählen Sie eine Lieferart" - -#: browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "Bitte wählen Sie eine Variation aus" - -#: browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "Bitte geben Sie eine Anzahl an" - -#. Default: "Post checkout" -#: browser/configlet.pt:92 -msgid "Post checkout" -msgstr "Nach dem Bestellvorgang" - -#: browser/checkout.py:247 -msgid "Previous step" -msgstr "Vorhergehender Schritt" - -#. Default: "Price" -#: browser/cart.pt:43 -msgid "Price" -msgstr "Preis" - -#. Default: "Price total" -#: browser/cart.pt:44 -msgid "Price total" -msgstr "Gesamtpreis" - -#: browser/checkout.py:246 -msgid "Print" -msgstr "Drucken" - -#. Default: "Product" -#: browser/cart.pt:41 -msgid "Product" -msgstr "Produkt" - -#. Default: "Product highlights" -#: browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "Produkte-Highlights" - -#. Default: "Product variations" -#: browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "Produktvariationen" - -#. Default: "Productname" -#: browser/configlet.pt:36 -msgid "Productname" -msgstr "Produktname" - -#. Default: "Related products" -#: browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "Verwandte Produkte" - -#. Default: "Remove" -#: browser/cart.pt:45 -msgid "Remove" -msgstr "Entfernen" - -#: browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "${count} Artikel vom Warenkorb entfernt" - -#: browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "Artikel vom Warenkorb entfernt" - -#. Default: "Salutation" -#: browser/address.pt:35 -msgid "Salutation" -msgstr "Anrede" - -#. Default: "Select the desired payment method" -#: browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "Wählen Sie die gewünschte Zahlungsmethode" - -#. Default: "Select the desired shipment method" -#: browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "Wählen Sie die gewünschte Lieferart" - -#. Default: "Select the desired shipment method for the following products:" -#: browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "Wählen Sie die gewünschte Lieferart für folgende Produkte:" - -#: browser/checkout.py:257 -msgid "Send order" -msgstr "Bestellung absenden" - -#. Default: "Shipment" -#: browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "Lieferung" - -#: browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "Warenkorb" - -#. Default: "Tax factor" -#: browser/configlet.pt:145 -msgid "Tax factor" -msgstr "Steuerfaktor" - -#. Default: "Tax included in product price" -#: browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "Steuer im Produktpreis inbegriffen" - -#. Default: "Tax name" -#: browser/configlet.pt:144 -msgid "Tax name" -msgstr "Steuername" - -#. Default: "Taxes" -#: browser/configlet.pt:138 -msgid "Taxes" -msgstr "Steuern" - -#. Default: "Thank you!" -#: browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "Vielen Dank!" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "Die Emailadresse welche Emails von PCommerce empfängt und versendet" - -#: browser/components/gtc.py:17 -msgid "" -"The general terms and conditions have to be accepted to finish your check " -"out." -msgstr "" -"Die Allgemeinen Geschäftsbedingungen müssen akzeptiert werden, bevor der " -"Bestellvorgang abgeschlossen werden kann." - -#. Default: "The name appearing in payment-terminals" -#: browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "Der Name, der in den Zahlungsmasken angezeigt wird" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: browser/configlet.pt:73 -msgid "" -"The path to the page holding the general terms and conditions to accept " -"before payment" -msgstr "" -"Der Pfad zu jener Seite, welche die Allgemeinen Geschäftsbedingungen " -"enthält, die vor der Zahlung akzeptiert werden müssen" - -#. Default: "The path to the page to be redirected to after checkout" -#: browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "" -"Der Pfad zu jener Seite, auf welche nach Abschluss des Bestellvorgangs " -"weitergeleitet werden soll." - -#. Default: "Total" -#: browser/cart.pt:78 -msgid "Total" -msgstr "Total" - -#. Default: "Total ${currency}:" -#: browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "Total ${currency}:" - -#. Default: "Total incl. ${taxname}" -#: browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "Total inkl. ${taxname}:" - -#: order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "Total inkl. ${tax}% ${taxname}" - -#. Default: "Total incl. charges" -#: browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "Total inkl. Gebühren" - -#. Default: "Total incl. charges and ${taxname}" -#: browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "Total inkl. Gebühren und ${taxname}" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "Total inkl. Gebühren und ${tax}% ${taxname}" - -#: content/variation.py:26 -msgid "Type" -msgstr "Typ" - -#. Default: "Variations" -#: browser/variations.pt:25 -msgid "Variations" -msgstr "Variationen" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: browser/components/confirmation.pt:12 -msgid "" -"We successfully received your order. An Email has been sent to you " -"containing all the order details." -msgstr "" -"Wir haben Ihre Bestellung erfolgreich erhalten. Ein Email mit allen " -"Informationen zu Ihrer Bestellung wurde an Sie versandt." - -#: browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "Sie haben noch keine Produkte in Ihrem Warenkorb" - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: browser/cart.pt:108 -msgid "" -"You have to be registered to check out your order, either ${log_in} if you " -"already have an account or head over to the ${registration_form} if you " -"don't." -msgstr "" -"Sie müssen angemeldet sein, um zur Kasse zu gehen; ${log_in}, falls Sie " -"bereits einen Benutzer haben oder füllen Sie das ${registration_form} aus " -"falls nicht." - -#. Default: "Your shopping cart" -#: browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "Ihr Warenkorb" - -#. Default: "Your shopping cart is empty" -#: browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "Ihr Warenkorb ist leer" - -#. Default: "ZIP / City" -#: browser/address.pt:185 -msgid "ZIP / City" -msgstr "PLZ / Ort" - -#. Default: "Zone" -#: browser/address.pt:253 -msgid "Zone" -msgstr "Zone" - -#. Default: "add" -#: browser/configlet.pt:192 -msgid "add" -msgstr "hinzufügen" - -#. Default: "add to cart" -#: browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "zum Warenkorb hinzufügen" - -#. Default: "Check out" -#: browser/checkout.pt:15 -msgid "checkout_title" -msgstr "Kasse" - -#. Default: "List of all orders and their statuses" -#: profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "Liste aller Bestellungen mit entsprechendem Status" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: browser/images.pt:40 -msgid "description_no_images" -msgstr "" -"Dieses Produkt hat keine weiteren Bilder. Um ein Bild hinzuzufügen, klicken " -"Sie den Knopf 'hinzufügen' oder fügen Sie Inhalte aus einem anderen Produkt " -"ein." - -#. Default: "No orders were found." -#: browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "Es wurden keine Bestellungen gefunden." - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" -"Dieses Produkt hat keine zusätzlichen Preise. Um einen Preis hinzuzufügen, " -"klicken Sie den Knopf 'Hinzufügen' oder fügen Sie Inhalte aus einem anderen " -"Produkt ein." - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: content/variation.py:52 -msgid "description_price" -msgstr "" -"Wenn mehrere Variationen aus verschiedenen Kategorien einen Einzelpreis " -"besitzen, wird bei der Preisfindung der Kombination der grössere Preis " -"gewählt." - -#. Default: "Shipment methods for this product" -#: content/product.py:68 -msgid "description_shipment_methods" -msgstr "Versandmöglichkeiten für dieses Produkt" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: order.py:475 -msgid "email_customer_body" -msgstr "" -"Sehr geehrte/r ${name}\n" -"\n" -"Ihre Bestellung wurde erfolgreich registriert. Nachfolgend finden Sie\n" -"eine komplette Übersicht Ihrer Bestellung.\n" -"\n" -"Bestellnummer: ${orderid}\n" -"\n" -"${cart}\n" -"Währung: ${currency}\n" -"\n" -"\n" -"Adresse:\n" -"${address}\n" -"\n" -"Zahlung:\n" -"${payment}\n" -"\n" -"Lieferung:\n" -"${shipments}\n" -"\n" -"\n" -"Falls Sie Fragen betreffend Ihrer Bestellung haben, zögern Sie nicht uns " -"unter\n" -"${from_email} zu kontaktieren.\n" -"\n" -"Freundliche Grüsse\n" -"\n" -"${from_name}" - -#. Default: "Confirmation e-mail" -#: order.py:402 -msgid "email_customer_title" -msgstr "Bestellungsbestätigung" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: order.py:454 -msgid "email_order_body" -msgstr "" -"Neue Bestellung von ${name}\n" -"\n" -"Bestellnummer: ${orderid}\n" -"\n" -"${cart}\n" -"Währung: ${currency}\n" -"\n" -"\n" -"Addresse:\n" -"${address}\n" -"\n" -"Zahlung:\n" -"${payment}\n" -"\n" -"Lieferung:\n" -"${shipments}" - -#. Default: "New order [${orderid}]" -#: order.py:393 -msgid "email_order_title" -msgstr "Neue Bestellung [${orderid}]" - -#. Default: "general terms and conditions" -#: browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "Allgemeinen Geschäftsbedingungen" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: browser/images.pt:35 -msgid "info_Image" -msgstr "" -"Sie befinden sich momentan auf der Bilderansicht einer Variation des " -"Produkts ${product}." - -#. Default: "You are currently looking at a variation of the product ${product}." -#: browser/variation.pt:25 -msgid "info_variation" -msgstr "" -"Sie befinden sich momentan auf einer Variation des Produkts ${product}." - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "" -"Sie befinden sich momentan auf der Preisansicht einer Variation des Produkts " -"${product}." - -#. Default: "Address" -#: browser/orders.py:73 -msgid "label_address" -msgstr "Adresse" - -#. Default: "Cancelled" -#: browser/orders.py:37 -msgid "label_cancelled" -msgstr "Abgebrochen" - -#. Default: "Currency" -#: browser/orders.py:59 -msgid "label_currency" -msgstr "Währung" - -#. Default: "Date" -#: browser/orders.py:56 -msgid "label_date" -msgstr "Datum" - -#. Default: "Failed" -#: browser/orders.py:36 -msgid "label_failed" -msgstr "Fehlgeschlagen" - -#. Default: "Initialized" -#: browser/orders.py:33 -msgid "label_initialized" -msgstr "Ausgelöst" - -#. Default: "Order id" -#: browser/orders.py:50 -msgid "label_order_id" -msgstr "Bestellnummer" - -#. Default: "Order status" -#: browser/orders.py:66 -msgid "label_order_state" -msgstr "Bestellstatus" - -#. Default: "Price total" -#: browser/orders.py:62 -msgid "label_price_total" -msgstr "Gesamtpreis" - -#. Default: "Processed" -#: browser/orders.py:35 -msgid "label_processed" -msgstr "Verarbeitet" - -#. Default: "Products" -#: browser/orders.py:77 -msgid "label_products" -msgstr "Produkte" - -#. Default: "Sent" -#: browser/orders.py:34 -msgid "label_sent" -msgstr "Gesendet" - -#. Default: "Shipment methods" -#: content/product.py:67 -msgid "label_shipment_methods" -msgstr "Versandarten" - -#. Default: "Shipment id's" -#: browser/orders.py:81 -msgid "label_shipmentids" -msgstr "Versandarten IDs" - -#. Default: "User id" -#: browser/orders.py:53 -msgid "label_user_id" -msgstr "Benutzername" - -#. Default: "Zone" -#: browser/orders.py:69 -msgid "label_zone" -msgstr "Zone" - -#. Default: "log in" -#: browser/cart.pt:101 -msgid "log_in" -msgstr "melden Sie sich an" - -#. Default: "Check out canceled" -#: browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "Bestellung abgebrochen" - -#. Default: "Check out failed" -#: browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "Bestellung fehlgeschlagen" - -#. Default: "${offer} instead of ${price}" -#: browser/macros.pt:11 -msgid "price_offer" -msgstr "${offer} statt ${price}" - -#. Default: "registration form" -#: browser/cart.pt:108 -msgid "registration_form" -msgstr "Registrierungsformular" - -#. Default: "remove" -#: browser/configlet.pt:168 -msgid "remove" -msgstr "löschen" - -#. Default: "Please supply an order id." -#: browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "Bitte geben Sie eine Bestellnummer ein." - -#. Default: "Please check the order id." -#: browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "Bitte überprüfen Sie die Bestellnummer." - -#. Default: "Manage orders" -#: browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "Bestellungen verwalten" - -#. Default: "Which one?" -#: browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "Welche?" - -#. Default: "Order details" -#: browser/order_details.pt:17 -msgid "title_order_details" -msgstr "Informationen zur Bestellung" - -#. Default: "The order could not be found." -#: browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "Die Bestellung konnte nicht gefunden werden." diff --git a/pcommerce/core/locales/de/LC_MESSAGES/plone.po b/pcommerce/core/locales/de/LC_MESSAGES/plone.po deleted file mode 100644 index fdd04af..0000000 --- a/pcommerce/core/locales/de/LC_MESSAGES/plone.po +++ /dev/null @@ -1,54 +0,0 @@ -msgid "" -msgstr "" -"POT-Creation-Date: 2008-04-07 14:15-100\n" -"Last-Translator: Simon Kaeser \n" -"Language-code: de\n" -"Language-name: Deutsch\n" -"Preferred-encodings: utf-8 latin1\n" -"Domain: plone\n" -"X-is-fallback-for: de-ch de-de de-at de-li de-lu\n" -"Project-Id-Version: pcommerce.core\n" -"PO-Revision-Date: 2007-11-01 10:18+0100\n" -"Language-Team: Simon Kaeser \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: German\n" -"X-Poedit-Country: GERMANY\n" -"X-Poedit-SourceCharset: utf-8\n" - -msgid "Price" -msgstr "Preis" - -msgid "A price" -msgstr "Ein Preis" - -msgid "Product" -msgstr "Produkt" - -msgid "A product" -msgstr "Ein Produkt" - -msgid "Variation" -msgstr "Variation" - -msgid "A variation of a product" -msgstr "Eine Variation eines Produkts" - -msgid "Variations" -msgstr "Variationen" - -msgid "Prices" -msgstr "Preise" - -msgid "PCommerce configuration" -msgstr "PCommerce Einstellungen" - -msgid "Shop" -msgstr "Shop" - -msgid "ShopFolder" -msgstr "Shopordner" - -msgid "Images" -msgstr "Bilder" diff --git a/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po b/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po deleted file mode 100644 index b409dad..0000000 --- a/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po +++ /dev/null @@ -1,771 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: 2011-09-05 08:59+0100\n" -"Last-Translator: Manuel Gualda Caballero \n" -"Language-Team: Spanish \n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: en\n" -"Language-Name: English\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: pcommerce\n" -"Language-code: es\n" -"Language-name: Spanish\n" -"Preferred-encodings: utf-8 latin1\n" -"X-is-fallback-for: es-es es-ar es-bo es-cl es-co es-cr es-do es-ec es-sv es-" -"gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n" -"X-Poedit-Language: Spanish\n" -"X-Poedit-Country: SPAIN\n" -"X-Poedit-SourceCharset: utf-8\n" - -#. Default: "Add image" -#: browser/images.pt:23 -msgid "Add image" -msgstr "Añadir imagen" - -#. Default: "Add price" -#: browser/prices.pt:24 -msgid "Add price" -msgstr "Añadir precio" - -#. Default: "Add variation" -#: browser/variations.pt:22 -msgid "Add variation" -msgstr "Añadir variación" - -#: browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "Se han añadido ${count} productos al carrito" - -#: browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "Producto añadido al carrito" - -#: content/variation.py:35 -msgid "Additional price" -msgstr "Precio adicional" - -#. Default: "Additional prices" -#: browser/prices.pt:27 -msgid "Additional prices" -msgstr "Precios adicionales" - -#: steps.py:10 -msgid "Address" -msgstr "Dirección" - -#. Default: "Address 1" -#: browser/address.pt:139 -msgid "Address 1" -msgstr "Dirección (1)" - -#. Default: "Address 2" -#: browser/address.pt:166 -msgid "Address 2" -msgstr "Dirección (2)" - -#. Default: "Amount" -#: browser/cart.pt:42 -msgid "Amount" -msgstr "Cantidad" - -#. Default: "Billing address" -#: browser/components/address.pt:12 -msgid "Billing address" -msgstr "Dirección de facturación" - -#: browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "Cancelar pedido" - -#. Default: "Check out" -#: browser/cart.pt:34 -msgid "Check out" -msgstr "Realizar pedido" - -#. Default: "Company" -#: browser/address.pt:120 -msgid "Company" -msgstr "Empresa y CIF" - -#. Default: "Confirmation" -#: browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "Confirmación del pedido" - -#: browser/checkout.py:255 -msgid "Continue shopping" -msgstr "Continuar comprando" - -#. Default: "Country" -#: browser/address.pt:224 -msgid "Country" -msgstr "País" - -#. Default: "Edit cart" -#: browser/cart.pt:120 -msgid "Edit cart" -msgstr "Modificar el carrito" - -#. Default: "Email" -#: browser/address.pt:294 -msgid "Email" -msgstr "Correo" - -#. Default: "Email address" -#: browser/configlet.pt:116 -#, fuzzy -msgid "Email address" -msgstr "Dirección de facturación" - -#. Default: "First name" -#: browser/address.pt:64 -msgid "First name" -msgstr "Nombre" - -#. Default: "GTC" -#: browser/configlet.pt:68 -msgid "GTC" -msgstr "CGC" - -#: content/product.py:59 -msgid "Hot product" -msgstr "Producto popular" - -#. Default: "I accept the ${link}" -#: browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "Acepto las ${link}" - -#. Default: "Image" -#: browser/images.pt:63 -msgid "Image" -msgstr "Imagen" - -#. Default: "Images" -#: browser/images.pt:26 -msgid "Images" -msgstr "Imágenes" - -#. Default: "Last name" -#: browser/address.pt:92 -msgid "Last name" -msgstr "Apellidos" - -#. Default: "Manage orders" -#: profiles/default/actions.xml -msgid "Manage orders" -msgstr "Administrar pedidos" - -#. Default: "Mr." -#: browser/address.pt:46 -msgid "Mr." -msgstr "Don" - -#. Default: "Mrs. / Ms." -#: browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "Doña" - -#: content/product.py:51 -msgid "New product" -msgstr "Nuevo producto" - -#. Default: "New products in our shop" -#: browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "Nuevos productos" - -#: browser/checkout.py:258 -msgid "Next step" -msgstr "Siguiente paso" - -#: browser/orders.py:110 -msgid "No" -msgstr "Nº" - -#. Default: "No of articles:" -#: browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "Nº de productos:" - -#. Default: "Overview" -#: browser/components/overview.pt:9 -msgid "Overview" -msgstr "Vista general" - -#. Default: "PCommerce configuration" -#: browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "Configuración de PCommerce" - -#. Default: "Payment" -#: browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "Pago" - -#: browser/checkout.py:331 -msgid "Payment canceled" -msgstr "Pago cancelado" - -#: browser/checkout.py:316 -msgid "Payment failed" -msgstr "Error en el pago" - -#. Default: "Phone" -#: browser/address.pt:322 -msgid "Phone" -msgstr "Teléfono" - -#: browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "" -"Por favor, introduzca un número con los decimales marcados con punto (ej.: " -"7.6)" - -#: browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "Por favor, indique un nombre de impuesto" - -#: browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "Por favor, indique un nombre de zona" - -#: browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "Por favor, seleccione un método de pago" - -#: browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "Por favor, seleccione un método de envío" - -#: browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "Por favor, seleccione una variación" - -#: browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "Por favor, especifique una cantidad" - -#. Default: "Post checkout" -#: browser/configlet.pt:92 -msgid "Post checkout" -msgstr "Tras el pedido" - -#: browser/checkout.py:247 -msgid "Previous step" -msgstr "Paso anterior" - -#. Default: "Price" -#: browser/cart.pt:43 -msgid "Price" -msgstr "Precio" - -#. Default: "Price total" -#: browser/cart.pt:44 -msgid "Price total" -msgstr "Precio total" - -#: browser/checkout.py:246 -msgid "Print" -msgstr "Imprimir" - -#. Default: "Product" -#: browser/cart.pt:41 -msgid "Product" -msgstr "Producto" - -#. Default: "Product highlights" -#: browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "Productos destacados" - -#. Default: "Product variations" -#: browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "Variaciones del producto" - -#. Default: "Productname" -#: browser/configlet.pt:36 -msgid "Productname" -msgstr "Nombre del producto" - -#. Default: "Related products" -#: browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "Productos relacionados" - -#. Default: "Remove" -#: browser/cart.pt:45 -msgid "Remove" -msgstr "Eliminar" - -#: browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "Se han eliminado ${count} productos del carrito" - -#: browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "Producto eliminado del carrito" - -#. Default: "Salutation" -#: browser/address.pt:35 -msgid "Salutation" -msgstr "Tratamiento" - -#. Default: "Select the desired payment method" -#: browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "Seleccione el método de pago deseado" - -#. Default: "Select the desired shipment method" -#: browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "Seleccione el método de envío deseado" - -#. Default: "Select the desired shipment method for the following products:" -#: browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "Seleccione el método de envío deseado para los siguientes productos:" - -#: browser/checkout.py:257 -msgid "Send order" -msgstr "Realizar el pedido" - -#. Default: "Shipment" -#: browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "Envío" - -#: browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "Carrito de la compra" - -#. Default: "Tax factor" -#: browser/configlet.pt:145 -msgid "Tax factor" -msgstr "Factor del impuesto" - -#. Default: "Tax included in product price" -#: browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "Impuestos incluidos en el precio del producto" - -#. Default: "Tax name" -#: browser/configlet.pt:144 -msgid "Tax name" -msgstr "Nombre del impuesto" - -#. Default: "Taxes" -#: browser/configlet.pt:138 -msgid "Taxes" -msgstr "Impuestos" - -#. Default: "Thank you!" -#: browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "¡Gracias!" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "" - -#: browser/components/gtc.py:17 -msgid "" -"The general terms and conditions have to be accepted to finish your check " -"out." -msgstr "" -"Debe aceptar las condiciones generales de contratación para poder realizar " -"el pedido." - -#. Default: "The name appearing in payment-terminals" -#: browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "Nombre que aparecerá en los terminales de pago" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: browser/configlet.pt:73 -msgid "" -"The path to the page holding the general terms and conditions to accept " -"before payment" -msgstr "" -"Ruta hacia la página que aloja las condiciones generales de contratación que " -"hay que aceptar antes de poder realizar el pago" - -#. Default: "The path to the page to be redirected to after checkout" -#: browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "" -"Ruta hacia la página a la que se será redirigido después de realizar el " -"pedido" - -#. Default: "Total" -#: browser/cart.pt:78 -msgid "Total" -msgstr "Total" - -#. Default: "Total ${currency}:" -#: browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "Total ${currency}:" - -#. Default: "Total incl. ${taxname}" -#: browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "Total con ${taxname}:" - -#: order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "Total con ${tax}% ${taxname}" - -#. Default: "Total incl. charges" -#: browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "Total con cargos" - -#. Default: "Total incl. charges and ${taxname}" -#: browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "Total con ${taxname} y cargos" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "Total con ${tax}% ${taxname} y cargos" - -#: content/variation.py:26 -msgid "Type" -msgstr "Tipo" - -#. Default: "Variations" -#: browser/variations.pt:25 -msgid "Variations" -msgstr "Variaciones" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: browser/components/confirmation.pt:12 -msgid "" -"We successfully received your order. An Email has been sent to you " -"containing all the order details." -msgstr "" -"Hemos recibido su pedido correctamente. Se le ha enviado un correo con los " -"detalles del mismo." - -#: browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "Todavía no ha añadido ningún producto a su carrito" - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: browser/cart.pt:108 -msgid "" -"You have to be registered to check out your order, either ${log_in} if you " -"already have an account or head over to the ${registration_form} if you " -"don't." -msgstr "" -"Debe haber iniciado sesión para poder realizar su pedido: ${log_in} (si ya " -"tiene una cuenta) o ${registration_form} (si todavía no la tiene)." - -#. Default: "Your shopping cart" -#: browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "Su carrito de la compra" - -#. Default: "Your shopping cart is empty" -#: browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "Su carrito de la compra está vacío" - -#. Default: "ZIP / City" -#: browser/address.pt:185 -msgid "ZIP / City" -msgstr "CP / Localidad" - -#. Default: "Zone" -#: browser/address.pt:253 -msgid "Zone" -msgstr "Zona" - -#. Default: "add" -#: browser/configlet.pt:192 -msgid "add" -msgstr "añadir" - -#. Default: "add to cart" -#: browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "añadir al carrito" - -#. Default: "Check out" -#: browser/checkout.pt:15 -msgid "checkout_title" -msgstr "Caja" - -#. Default: "List of all orders and their statuses" -#: profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "Lista de todos los pedidos y sus estados" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: browser/images.pt:40 -msgid "description_no_images" -msgstr "" -"Este producto no tiene imágenes. Para añadir una imagen, pulse el botón de " -"añadir o pegue el contenido desde otro lugar." - -#. Default: "No orders were found." -#: browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "" -"Este producto no tiene precios adicionales. Para añadir un precio, pulse el " -"botón de añadir o pegue el contenido desde otro lugar." - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" -"Este producto no tiene precios adicionales. Para añadir un precio, pulse el " -"botón de añadir o pegue el contenido desde otro lugar." - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: content/variation.py:52 -msgid "description_price" -msgstr "" -"If multiple selected variations in different categories have unit prices, " -"the greater price will be accounted for in pricing of the selected " -"combination." - -#. Default: "Shipment methods for this product" -#: content/product.py:68 -msgid "description_shipment_methods" -msgstr "Métodos de envío para este producto" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: order.py:475 -msgid "email_customer_body" -msgstr "" -"Estimado/a ${name}\n" -"\n" -"Su pedido ha sido correctamente registrado. Vea un resumen del mismo:\n" -"\n" -"ID del pedido: ${orderid}\n" -"\n" -"${cart}\n" -"Moneda: ${currency}\n" -"\n" -"\n" -"Domicilio:\n" -"${address}\n" -"\n" -"Pago:\n" -"${payment}\n" -"\n" -"Envío:\n" -"${shipments}\n" -"\n" -"\n" -"Si tiene alguna pregunta sobre su compra, no dude en escribirnos a " -"${from_email}.\n" -"\n" -"Atentamente,\n" -"\n" -"${from_name}" - -#. Default: "Confirmation e-mail" -#: order.py:402 -msgid "email_customer_title" -msgstr "Confirmación de su pedido" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: order.py:454 -msgid "email_order_body" -msgstr "" -"Nuevo pedido realizado por ${name}\n" -"\n" -"ID del pedido: ${orderid}\n" -"\n" -"${cart}\n" -"Moneda: ${currency}\n" -"\n" -"\n" -"Dirección:\n" -"${address}\n" -"\n" -"Pago:\n" -"${payment}\n" -"\n" -"Envío:\n" -"${shipments}" - -#. Default: "New order [${orderid}]" -#: order.py:393 -msgid "email_order_title" -msgstr "Nuevo pedido [${orderid}]" - -#. Default: "general terms and conditions" -#: browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "condiciones generales de contratación" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: browser/images.pt:35 -msgid "info_Image" -msgstr "" -"Actualmente está viendo las imágenes de una variación del producto " -"${product}." - -#. Default: "You are currently looking at a variation of the product ${product}." -#: browser/variation.pt:25 -msgid "info_variation" -msgstr "Actualmente está viendo una variación del producto ${product}." - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "" -"Actualmente está viendo los precios de una variación del producto ${product}." - -#. Default: "Address" -#: browser/orders.py:73 -msgid "label_address" -msgstr "Dirección" - -#. Default: "Cancelled" -#: browser/orders.py:37 -msgid "label_cancelled" -msgstr "Cancelado" - -#. Default: "Currency" -#: browser/orders.py:59 -msgid "label_currency" -msgstr "Moneda" - -#. Default: "Date" -#: browser/orders.py:56 -msgid "label_date" -msgstr "Fecha" - -#. Default: "Failed" -#: browser/orders.py:36 -msgid "label_failed" -msgstr "Malogrado" - -#. Default: "Initialized" -#: browser/orders.py:33 -msgid "label_initialized" -msgstr "Iniciado" - -#. Default: "Order id" -#: browser/orders.py:50 -msgid "label_order_id" -msgstr "ID del pedido" - -#. Default: "Order status" -#: browser/orders.py:66 -msgid "label_order_state" -msgstr "Estado del pedido" - -#. Default: "Price total" -#: browser/orders.py:62 -msgid "label_price_total" -msgstr "Precio total" - -#. Default: "Processed" -#: browser/orders.py:35 -msgid "label_processed" -msgstr "Procesado" - -#. Default: "Products" -#: browser/orders.py:77 -msgid "label_products" -msgstr "Productos" - -#. Default: "Sent" -#: browser/orders.py:34 -msgid "label_sent" -msgstr "Enviar" - -#. Default: "Shipment methods" -#: content/product.py:67 -msgid "label_shipment_methods" -msgstr "Métodos de envío" - -#. Default: "Shipment id's" -#: browser/orders.py:81 -msgid "label_shipmentids" -msgstr "ID de los envíos" - -#. Default: "User id" -#: browser/orders.py:53 -msgid "label_user_id" -msgstr "ID del usuario" - -#. Default: "Zone" -#: browser/orders.py:69 -msgid "label_zone" -msgstr "Zona" - -#. Default: "log in" -#: browser/cart.pt:101 -msgid "log_in" -msgstr "iniciar sesión" - -#. Default: "Check out canceled" -#: browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "Pedido cancelado" - -#. Default: "Check out failed" -#: browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "Error en el pedido" - -#. Default: "${offer} instead of ${price}" -#: browser/macros.pt:11 -msgid "price_offer" -msgstr "${offer} en lugar de ${price}" - -#. Default: "registration form" -#: browser/cart.pt:108 -msgid "registration_form" -msgstr "formulario de registro" - -#. Default: "remove" -#: browser/configlet.pt:168 -msgid "remove" -msgstr "eliminar" - -#. Default: "Please supply an order id." -#: browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "Por favor, facilite un número (ID) de pedido." - -#. Default: "Please check the order id." -#: browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "Por favor, compruebe el número (ID) de pedido." - -#. Default: "Manage orders" -#: browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "Administrar pedidos" - -#. Default: "Which one?" -#: browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "¿Cuál?" - -#. Default: "Order details" -#: browser/order_details.pt:17 -msgid "title_order_details" -msgstr "Detalles del pedido" - -#. Default: "The order could not be found." -#: browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "El pedido no ha podido ser encontrado." diff --git a/pcommerce/core/locales/es/LC_MESSAGES/plone.po b/pcommerce/core/locales/es/LC_MESSAGES/plone.po deleted file mode 100644 index c7133d8..0000000 --- a/pcommerce/core/locales/es/LC_MESSAGES/plone.po +++ /dev/null @@ -1,56 +0,0 @@ -msgid "" -msgstr "" -"POT-Creation-Date: 2011-08-31 08:16+0000\n" -"PO-Revision-Date: 2011-09-04 19:32+0100\n" -"Last-Translator: Manuel Gualda Caballero \n" -"Language-Team: Spanish \n" -"Language: es\n" -"Language-code: es\n" -"Language-name: Spanish\n" -"Preferred-encodings: utf-8 latin1\n" -"Domain: plone\n" -"X-is-fallback-for: es-es es-ar es-bo es-cl es-co es-cr es-do es-ec es-sv es-gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n" -"Project-Id-Version: pcommerce.core\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Poedit-Language: Spanish\n" -"X-Poedit-Country: SPAIN\n" -"X-Poedit-SourceCharset: utf-8\n" - -msgid "Price" -msgstr "Precio" - -msgid "A price" -msgstr "Un precio" - -msgid "Product" -msgstr "Producto" - -msgid "A product" -msgstr "Un producto" - -msgid "Variation" -msgstr "Variación" - -msgid "A variation of a product" -msgstr "Una variación de un producto" - -msgid "Variations" -msgstr "Variaciones" - -msgid "Prices" -msgstr "Precios" - -msgid "PCommerce configuration" -msgstr "Configuración de PCommerce" - -msgid "Shop" -msgstr "Tienda" - -msgid "ShopFolder" -msgstr "Carpeta de tienda" - -msgid "Images" -msgstr "Imágenes" - diff --git a/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po b/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po deleted file mode 100755 index e843a02..0000000 --- a/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po +++ /dev/null @@ -1,760 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: 2007-11-01 10:18+0100\n" -"Last-Translator: Steve Beyeler \n" -"Language-Team: Français \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language-code: fr\n" -"Language-name: Français\n" -"Preferred-encodings: utf-8 latin1\n" -"Domain: pcommerce\n" -"X-is-fallback-for: fr-ch fr-fr fr-be\n" -"X-Poedit-Language: Français\n" -"X-Poedit-Country: FRANCE\n" -"X-Poedit-SourceCharset: utf-8\n" - -#. Default: "Add image" -#: browser/images.pt:23 -msgid "Add image" -msgstr "Ajouter une image" - -#. Default: "Add price" -#: browser/prices.pt:24 -msgid "Add price" -msgstr "Ajouter un prix" - -#. Default: "Add variation" -#: browser/variations.pt:22 -msgid "Add variation" -msgstr "Ajouter une variation" - -#: browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "${count} articles ajoutés au panier" - -#: browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "Article ajouté au panier" - -#: content/variation.py:35 -msgid "Additional price" -msgstr "Supplément de prix" - -#. Default: "Additional prices" -#: browser/prices.pt:27 -msgid "Additional prices" -msgstr "Prix supplémentaires" - -#: steps.py:10 -msgid "Address" -msgstr "Adresse" - -#. Default: "Address 1" -#: browser/address.pt:139 -msgid "Address 1" -msgstr "Adresse 1" - -#. Default: "Address 2" -#: browser/address.pt:166 -msgid "Address 2" -msgstr "Adresse 2" - -#. Default: "Amount" -#: browser/cart.pt:42 -msgid "Amount" -msgstr "Nombre" - -#. Default: "Billing address" -#: browser/components/address.pt:12 -msgid "Billing address" -msgstr "Adresse de facturation" - -#: browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "Annuler la commande" - -#. Default: "Check out" -#: browser/cart.pt:34 -msgid "Check out" -msgstr "Passer à la caisse" - -#. Default: "Company" -#: browser/address.pt:120 -msgid "Company" -msgstr "Société" - -#. Default: "Confirmation" -#: browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "Confirmation" - -#: browser/checkout.py:255 -msgid "Continue shopping" -msgstr "Continuer les achats" - -#. Default: "Country" -#: browser/address.pt:224 -msgid "Country" -msgstr "Pays" - -#. Default: "Edit cart" -#: browser/cart.pt:120 -msgid "Edit cart" -msgstr "Editer le panier" - -#. Default: "Email" -#: browser/address.pt:294 -msgid "Email" -msgstr "Courriel" - -#. Default: "Email address" -#: browser/configlet.pt:116 -#, fuzzy -msgid "Email address" -msgstr "Adresse de facturation" - -#. Default: "First name" -#: browser/address.pt:64 -msgid "First name" -msgstr "Prénom" - -#. Default: "GTC" -#: browser/configlet.pt:68 -msgid "GTC" -msgstr "CGA" - -#: content/product.py:59 -msgid "Hot product" -msgstr "Produit TOP" - -#. Default: "I accept the ${link}" -#: browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "J'accèpte les ${link}" - -#. Default: "Image" -#: browser/images.pt:63 -msgid "Image" -msgstr "Image" - -#. Default: "Images" -#: browser/images.pt:26 -msgid "Images" -msgstr "Images" - -#. Default: "Last name" -#: browser/address.pt:92 -msgid "Last name" -msgstr "Nom" - -#. Default: "Manage orders" -#: profiles/default/actions.xml -msgid "Manage orders" -msgstr "Gérer les commandes" - -#. Default: "Mr." -#: browser/address.pt:46 -msgid "Mr." -msgstr "M." - -#. Default: "Mrs. / Ms." -#: browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "Mme" - -#: content/product.py:51 -msgid "New product" -msgstr "Nouveau produit" - -#. Default: "New products in our shop" -#: browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "Actualités dans notre shop" - -#: browser/checkout.py:258 -msgid "Next step" -msgstr "Prochaine étape" - -#: browser/orders.py:110 -msgid "No" -msgstr "Numéro d'article" - -#. Default: "No of articles:" -#: browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "Nombre d'articles:" - -#. Default: "Overview" -#: browser/components/overview.pt:9 -msgid "Overview" -msgstr "Aperçu" - -#. Default: "PCommerce configuration" -#: browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "Paramètres PCommerce" - -#. Default: "Payment" -#: browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "Mode de paiement" - -#: browser/checkout.py:331 -msgid "Payment canceled" -msgstr "Paiement annulé" - -#: browser/checkout.py:316 -msgid "Payment failed" -msgstr "Paiement échoué" - -#. Default: "Phone" -#: browser/address.pt:322 -msgid "Phone" -msgstr "Téléphone" - -#: browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "Veuillez entrer un chiffre décimal (p.ex. 7.6)" - -#: browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "Veuillez indiquer un titre pour la taxe" - -#: browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "Veuillez indiquer un titre pour la zone" - -#: browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "Veuillez choisir un mode de paiement" - -#: browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "Veuillez indiquer un type de livraison" - -#: browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "Veuillez choisir une variation" - -#: browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "Veuillez indiquer un nombre" - -#. Default: "Post checkout" -#: browser/configlet.pt:92 -msgid "Post checkout" -msgstr "Après la commande" - -#: browser/checkout.py:247 -msgid "Previous step" -msgstr "Etape précédente" - -#. Default: "Price" -#: browser/cart.pt:43 -msgid "Price" -msgstr "Prix" - -#. Default: "Price total" -#: browser/cart.pt:44 -msgid "Price total" -msgstr "Prix total" - -#: browser/checkout.py:246 -msgid "Print" -msgstr "Imprimer" - -#. Default: "Product" -#: browser/cart.pt:41 -msgid "Product" -msgstr "Produit" - -#. Default: "Product highlights" -#: browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "Produits TOP" - -#. Default: "Product variations" -#: browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "Variations du produit" - -#. Default: "Productname" -#: browser/configlet.pt:36 -msgid "Productname" -msgstr "Nom du produit" - -#. Default: "Related products" -#: browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "Produits apparentés" - -#. Default: "Remove" -#: browser/cart.pt:45 -msgid "Remove" -msgstr "Supprimer" - -#: browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "${count} articles supprimés du panier" - -#: browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "Article supprimé du panier" - -#. Default: "Salutation" -#: browser/address.pt:35 -msgid "Salutation" -msgstr "Titre" - -#. Default: "Select the desired payment method" -#: browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "Veuillez choisir le mode de paiement désiré" - -#. Default: "Select the desired shipment method" -#: browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "Veuillez choisir le type de livraison désiré" - -#. Default: "Select the desired shipment method for the following products:" -#: browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "" -"Veuillez choisir le type de livraison désiré pour les produits suivants:" - -#: browser/checkout.py:257 -msgid "Send order" -msgstr "Envoyer la commande" - -#. Default: "Shipment" -#: browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "Livraison" - -#: browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "Panier" - -#. Default: "Tax factor" -#: browser/configlet.pt:145 -msgid "Tax factor" -msgstr "Facteur taxe" - -#. Default: "Tax included in product price" -#: browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "Taxe inclue dans le prix du produit" - -#. Default: "Tax name" -#: browser/configlet.pt:144 -msgid "Tax name" -msgstr "Titre de la taxe" - -#. Default: "Taxes" -#: browser/configlet.pt:138 -msgid "Taxes" -msgstr "Taxes" - -#. Default: "Thank you!" -#: browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "Meilleurs remerciements !" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "" - -#: browser/components/gtc.py:17 -msgid "" -"The general terms and conditions have to be accepted to finish your check " -"out." -msgstr "" -"Il est nécéssaire d'accèpter les condition générales d'affaires avant de " -"compléter terminer la commande." - -#. Default: "The name appearing in payment-terminals" -#: browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "Le nom apparaissant dans les masques de paiement" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: browser/configlet.pt:73 -msgid "" -"The path to the page holding the general terms and conditions to accept " -"before payment" -msgstr "" -"Le chemin d'accès à la page contenant les conditions générales d'affaires " -"qui doivent être acceptées avant le paiement" - -#. Default: "The path to the page to be redirected to after checkout" -#: browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "Le chemin d'accès à la page à afficher une fois la commande complétée." - -#. Default: "Total" -#: browser/cart.pt:78 -msgid "Total" -msgstr "Total" - -#. Default: "Total ${currency}:" -#: browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "Total ${currency}:" - -#. Default: "Total incl. ${taxname}" -#: browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "Total ${taxname} incl.:" - -#: order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "Total ${tax}% ${taxname} incl." - -#. Default: "Total incl. charges" -#: browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "Total charges comprises" - -#. Default: "Total incl. charges and ${taxname}" -#: browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "Total charges et ${taxname} comprises" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "Total charges et ${tax}% ${taxname} comprises" - -#: content/variation.py:26 -msgid "Type" -msgstr "Type" - -#. Default: "Variations" -#: browser/variations.pt:25 -msgid "Variations" -msgstr "Variations" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: browser/components/confirmation.pt:12 -msgid "" -"We successfully received your order. An Email has been sent to you " -"containing all the order details." -msgstr "" -"Nous avons reçu votre commande avec succès. Un courriel contenant toutes les " -"information relatives à votre commande vous a été envoyé." - -#: browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "Vous n'avez pas encore placé de produits dans votre panier" - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: browser/cart.pt:108 -msgid "" -"You have to be registered to check out your order, either ${log_in} if you " -"already have an account or head over to the ${registration_form} if you " -"don't." -msgstr "" -"Il faut être connecté pour pouvoir passer à la caisse; ${log_in} si vous " -"disposez déjà d'un utilisateur, sinon veuillez remplir le " -"${registration_form} ." - -#. Default: "Your shopping cart" -#: browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "Votre panier" - -#. Default: "Your shopping cart is empty" -#: browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "Votre panier est vide" - -#. Default: "ZIP / City" -#: browser/address.pt:185 -msgid "ZIP / City" -msgstr "Code postal / Localité" - -#. Default: "Zone" -#: browser/address.pt:253 -msgid "Zone" -msgstr "Zone" - -#. Default: "add" -#: browser/configlet.pt:192 -msgid "add" -msgstr "ajouter" - -#. Default: "add to cart" -#: browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "ajouter au panier" - -#. Default: "Check out" -#: browser/checkout.pt:15 -msgid "checkout_title" -msgstr "Caisse" - -#. Default: "List of all orders and their statuses" -#: profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "Affiche toutes les commandes ainsi que leur état" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: browser/images.pt:40 -msgid "description_no_images" -msgstr "" -"Ce produit ne dispose pas davantage d'images. Pour ajouter une image " -"veuillez cliquer le bouton ajouter ou ajoutez les éléments depuis un autre " -"produit." - -#. Default: "No orders were found." -#: browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "Aucune commande n'a été trouvé." - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" -"Ce produit ne dispose pas de prix supplémentaires. Pour ajouter un prix " -"veuillez cliquer ajouter ou ajoutez les éléments depuis un autre produit." - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: content/variation.py:52 -msgid "description_price" -msgstr "" -"Si plusieurs variations de différentes catégories disposent d'un prix " -"unique, le prix combiné des produits correspondra au prix le plus élevé." - -#. Default: "Shipment methods for this product" -#: content/product.py:68 -msgid "description_shipment_methods" -msgstr "Types de livraison disponibles pour ce produit" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: order.py:475 -msgid "email_customer_body" -msgstr "" -"Très cher/chère ${name}\n" -"\n" -"Votre commande a été enregistrée avec succès. Veuillez trouver l'aperçu\n" -"complet de votre commande ci-après.\n" -"\n" -"Numéro de commande: ${orderid}\n" -"\n" -"${cart}\n" -"Monnaie: ${currency}\n" -"\n" -"\n" -"Adresse:\n" -"${address}\n" -"\n" -"Paiement:\n" -"${payment}\n" -"\n" -"Livraison:\n" -"${shipments}\n" -"\n" -"\n" -"Si vous avez des questions concernant votre achat, n'hésitez pas à nous\n" -"contacter par ${from_email}.\n" -"\n" -"Meilleurs remerciements\n" -"\n" -"${from_name}" - -#. Default: "Confirmation e-mail" -#: order.py:402 -msgid "email_customer_title" -msgstr "Confirmation de commande" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: order.py:454 -msgid "email_order_body" -msgstr "" -"Nouvelle commande par ${name}\n" -"\n" -"Numéro de commande: ${orderid}\n" -"\n" -"${cart}\n" -"Monnaie: ${currency}\n" -"\n" -"\n" -"Adresse:\n" -"${address}\n" -"\n" -"Paiement:\n" -"${payment}\n" -"\n" -"Livraison:\n" -"${shipments}" - -#. Default: "New order [${orderid}]" -#: order.py:393 -msgid "email_order_title" -msgstr "Nouvelle commande [${orderid}]" - -#. Default: "general terms and conditions" -#: browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "Conditions générales d'affaires" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: browser/images.pt:35 -msgid "info_Image" -msgstr "Ceci est l'affichage des images d'une variation du produit ${product}." - -#. Default: "You are currently looking at a variation of the product ${product}." -#: browser/variation.pt:25 -msgid "info_variation" -msgstr "Ceci est la variation du produit ${product}." - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "Ceci est l'affichage des prix d'une variation du produit ${product}." - -#. Default: "Address" -#: browser/orders.py:73 -msgid "label_address" -msgstr "Adresse" - -#. Default: "Cancelled" -#: browser/orders.py:37 -msgid "label_cancelled" -msgstr "Annulé" - -#. Default: "Currency" -#: browser/orders.py:59 -msgid "label_currency" -msgstr "Monnaie" - -#. Default: "Date" -#: browser/orders.py:56 -msgid "label_date" -msgstr "Date" - -#. Default: "Failed" -#: browser/orders.py:36 -msgid "label_failed" -msgstr "Echoué" - -#. Default: "Initialized" -#: browser/orders.py:33 -msgid "label_initialized" -msgstr "Passée" - -#. Default: "Order id" -#: browser/orders.py:50 -msgid "label_order_id" -msgstr "Numéro de commande" - -#. Default: "Order status" -#: browser/orders.py:66 -msgid "label_order_state" -msgstr "Etat de la commande" - -#. Default: "Price total" -#: browser/orders.py:62 -msgid "label_price_total" -msgstr "Prix total" - -#. Default: "Processed" -#: browser/orders.py:35 -msgid "label_processed" -msgstr "Traitée" - -#. Default: "Products" -#: browser/orders.py:77 -msgid "label_products" -msgstr "Produits" - -#. Default: "Sent" -#: browser/orders.py:34 -msgid "label_sent" -msgstr "Envoyée" - -#. Default: "Shipment methods" -#: content/product.py:67 -msgid "label_shipment_methods" -msgstr "Types de livraison" - -#. Default: "Shipment id's" -#: browser/orders.py:81 -msgid "label_shipmentids" -msgstr "Identifiants des types de livraison" - -#. Default: "User id" -#: browser/orders.py:53 -msgid "label_user_id" -msgstr "Nom d'utilisateur" - -#. Default: "Zone" -#: browser/orders.py:69 -msgid "label_zone" -msgstr "Zone" - -#. Default: "log in" -#: browser/cart.pt:101 -msgid "log_in" -msgstr "Veuillez vous connecter" - -#. Default: "Check out canceled" -#: browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "Commande annulée" - -#. Default: "Check out failed" -#: browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "Commande échouée" - -#. Default: "${offer} instead of ${price}" -#: browser/macros.pt:11 -msgid "price_offer" -msgstr "${offer} au lieu de ${price}" - -#. Default: "registration form" -#: browser/cart.pt:108 -msgid "registration_form" -msgstr "formulaire d'enregistrement" - -#. Default: "remove" -#: browser/configlet.pt:168 -msgid "remove" -msgstr "supprimer" - -#. Default: "Please supply an order id." -#: browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "Veuillez indiquer un numéro de commande." - -#. Default: "Please check the order id." -#: browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "Veuillez contrôler le numéro de commande." - -#. Default: "Manage orders" -#: browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "Gérer les commandes" - -#. Default: "Which one?" -#: browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "Laquelle?" - -#. Default: "Order details" -#: browser/order_details.pt:17 -msgid "title_order_details" -msgstr "Informations à propos de la commande" - -#. Default: "The order could not be found." -#: browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "La commande n'a pas été trouvée." diff --git a/pcommerce/core/locales/fr/LC_MESSAGES/plone.po b/pcommerce/core/locales/fr/LC_MESSAGES/plone.po deleted file mode 100755 index aae0596..0000000 --- a/pcommerce/core/locales/fr/LC_MESSAGES/plone.po +++ /dev/null @@ -1,55 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2008-04-07 14:15-100\n" -"PO-Revision-Date: 2007-11-01 10:18+0100\n" -"Last-Translator: Steve Beyeler \n" -"Language-Team: Français \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language-code: fr\n" -"Language-name: Français\n" -"Preferred-encodings: utf-8 latin1\n" -"Domain: plone\n" -"X-is-fallback-for: fr-ch fr-fr fr-be\n" -"X-Poedit-Language: Français\n" -"X-Poedit-Country: FRANCE\n" -"X-Poedit-SourceCharset: utf-8\n" - -msgid "Price" -msgstr "Prix" - -msgid "A price" -msgstr "Un prix" - -msgid "Product" -msgstr "Produit" - -msgid "A product" -msgstr "Un produit" - -msgid "Variation" -msgstr "Variation" - -msgid "A variation of a product" -msgstr "Un variation d'un produit" - -msgid "Variations" -msgstr "Variations" - -msgid "Prices" -msgstr "Prix" - -msgid "PCommerce configuration" -msgstr "Paramètres PCommerce" - -msgid "Shop" -msgstr "Shop" - -msgid "ShopFolder" -msgstr "Dossier shop" - -msgid "Images" -msgstr "Images" diff --git a/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po b/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po deleted file mode 100644 index 91e8426..0000000 --- a/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po +++ /dev/null @@ -1,754 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" -"Last-Translator: Albert Peschar \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: nl\n" -"Language-Name: Nederlands\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: pcommerce\n" - -#. Default: "Add image" -#: browser/images.pt:23 -msgid "Add image" -msgstr "Voeg afbeelding toe" - -#. Default: "Add price" -#: browser/prices.pt:24 -msgid "Add price" -msgstr "Voeg prijs toe" - -#. Default: "Add variation" -#: browser/variations.pt:22 -msgid "Add variation" -msgstr "Voeg variant toe" - -#: browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "${count} items toegevoegd aan winkelmandje" - -#: browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "Item toegevoegd aan winkelmandje" - -#: content/variation.py:35 -msgid "Additional price" -msgstr "Extra prijs" - -#. Default: "Additional prices" -#: browser/prices.pt:27 -msgid "Additional prices" -msgstr "Extra prijzen" - -#: steps.py:10 -msgid "Address" -msgstr "Adres" - -#. Default: "Address 1" -#: browser/address.pt:139 -msgid "Address 1" -msgstr "Adres 1" - -#. Default: "Address 2" -#: browser/address.pt:166 -msgid "Address 2" -msgstr "Adres 2" - -#. Default: "Amount" -#: browser/cart.pt:42 -msgid "Amount" -msgstr "Aantal" - -#. Default: "Billing address" -#: browser/components/address.pt:12 -msgid "Billing address" -msgstr "Factuuradres" - -#: browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "Bestelling annuleren" - -#. Default: "Check out" -#: browser/cart.pt:34 -msgid "Check out" -msgstr "Bestellen" - -#. Default: "Company" -#: browser/address.pt:120 -msgid "Company" -msgstr "Bedrijf" - -#. Default: "Confirmation" -#: browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "Bevestiging" - -#: browser/checkout.py:255 -msgid "Continue shopping" -msgstr "Verder winkelen" - -#. Default: "Country" -#: browser/address.pt:224 -msgid "Country" -msgstr "Land" - -#. Default: "Edit cart" -#: browser/cart.pt:120 -msgid "Edit cart" -msgstr "Winkelmandje bewerken" - -#. Default: "Email" -#: browser/address.pt:294 -msgid "Email" -msgstr "E-mail" - -#. Default: "Email address" -#: browser/configlet.pt:116 -#, fuzzy -msgid "Email address" -msgstr "Factuuradres" - -#. Default: "First name" -#: browser/address.pt:64 -msgid "First name" -msgstr "Voornaam" - -#. Default: "GTC" -#: browser/configlet.pt:68 -msgid "GTC" -msgstr "Voorwaarden-pagina" - -#: content/product.py:59 -msgid "Hot product" -msgstr "Populair artikel" - -#. Default: "I accept the ${link}" -#: browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "Ik ga akkoord met de ${link}" - -#. Default: "Image" -#: browser/images.pt:63 -msgid "Image" -msgstr "Afbeelding" - -#. Default: "Images" -#: browser/images.pt:26 -msgid "Images" -msgstr "Afbeeldingen" - -#. Default: "Last name" -#: browser/address.pt:92 -msgid "Last name" -msgstr "Achternaam" - -#. Default: "Manage orders" -#: profiles/default/actions.xml -msgid "Manage orders" -msgstr "Bestellingen beheren" - -#. Default: "Mr." -#: browser/address.pt:46 -msgid "Mr." -msgstr "Dhr." - -#. Default: "Mrs. / Ms." -#: browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "Mw. / Mej." - -#: content/product.py:51 -msgid "New product" -msgstr "Nieuw artikel" - -#. Default: "New products in our shop" -#: browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "Nieuwe artikelen in onze winkel" - -#: browser/checkout.py:258 -msgid "Next step" -msgstr "Volgende stap" - -#: browser/orders.py:110 -msgid "No" -msgstr "Aantal" - -#. Default: "No of articles:" -#: browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "Aantal artikelen:" - -#. Default: "Overview" -#: browser/components/overview.pt:9 -msgid "Overview" -msgstr "Overzicht" - -#. Default: "PCommerce configuration" -#: browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "PCommerce-instellingen" - -#. Default: "Payment" -#: browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "Betaling" - -#: browser/checkout.py:331 -msgid "Payment canceled" -msgstr "Betaling geannuleerd" - -#: browser/checkout.py:316 -msgid "Payment failed" -msgstr "Betaling mislukt" - -#. Default: "Phone" -#: browser/address.pt:322 -msgid "Phone" -msgstr "Telefoon" - -#: browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "Vul alstublieft een decimaal getal in (bijv. 7.6)" - -#: browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "Geef alstublieft een naam van de belasting op" - -#: browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "Geef alstublieft een zone-naam op" - -#: browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "Kies een betaalmethode." - -#: browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "Kies een verzendmethode." - -#: browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "Kies een variant." - -#: browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "Geef een aantal op." - -#. Default: "Post checkout" -#: browser/configlet.pt:92 -msgid "Post checkout" -msgstr "Pagina na bestellen" - -#: browser/checkout.py:247 -msgid "Previous step" -msgstr "Vorige stap" - -#. Default: "Price" -#: browser/cart.pt:43 -msgid "Price" -msgstr "Prijs" - -#. Default: "Price total" -#: browser/cart.pt:44 -msgid "Price total" -msgstr "Totale prijs" - -#: browser/checkout.py:246 -msgid "Print" -msgstr "Afdrukken" - -#. Default: "Product" -#: browser/cart.pt:41 -msgid "Product" -msgstr "Artikel" - -#. Default: "Product highlights" -#: browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "Uitgelichte artikelen" - -#. Default: "Product variations" -#: browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "Varianten van dit artikel" - -#. Default: "Productname" -#: browser/configlet.pt:36 -msgid "Productname" -msgstr "Artikelnaam" - -#. Default: "Related products" -#: browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "Verwante artikelen" - -#. Default: "Remove" -#: browser/cart.pt:45 -msgid "Remove" -msgstr "Verwijderen" - -#: browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "${count} items verwijderd uit winkelmandje" - -#: browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "Item verwijderd uit winkelmandje" - -#. Default: "Salutation" -#: browser/address.pt:35 -msgid "Salutation" -msgstr "Aanhef" - -#. Default: "Select the desired payment method" -#: browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "Kies de gewenste betaalmethode" - -#. Default: "Select the desired shipment method" -#: browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "Kies de gewenste verzendmethode" - -#. Default: "Select the desired shipment method for the following products:" -#: browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "Kies de gewenste verzendmethode voor de volgende artikelen:" - -#: browser/checkout.py:257 -msgid "Send order" -msgstr "Bestelling versturen" - -#. Default: "Shipment" -#: browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "Verzending" - -#: browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "Winkelmandje" - -#. Default: "Tax factor" -#: browser/configlet.pt:145 -msgid "Tax factor" -msgstr "Belastingpercentage" - -#. Default: "Tax included in product price" -#: browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "Belasting bij prijs inbegrepen" - -#. Default: "Tax name" -#: browser/configlet.pt:144 -msgid "Tax name" -msgstr "Belastingnaam" - -#. Default: "Taxes" -#: browser/configlet.pt:138 -msgid "Taxes" -msgstr "Belastingen" - -#. Default: "Thank you!" -#: browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "Dank u!" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "" - -#: browser/components/gtc.py:17 -msgid "" -"The general terms and conditions have to be accepted to finish your check " -"out." -msgstr "" -"U kunt de bestelling pas afronden als u de algemene voorwaarden aanvaardt." - -#. Default: "The name appearing in payment-terminals" -#: browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "De naam die verschijnt op afschriften" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: browser/configlet.pt:73 -msgid "" -"The path to the page holding the general terms and conditions to accept " -"before payment" -msgstr "" -"Het pad naar de pagina waarop de voorwaarden staan die men dient te " -"aanvaarden voor betaling" - -#. Default: "The path to the page to be redirected to after checkout" -#: browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "Het pad naar de pagina waarheen na betaling doorgestuurd wordt." - -#. Default: "Total" -#: browser/cart.pt:78 -msgid "Total" -msgstr "Totaal" - -#. Default: "Total ${currency}:" -#: browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "Totaal ${currency}:" - -#. Default: "Total incl. ${taxname}" -#: browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "Totaal incl. ${taxname}" - -#: order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "Totaal incl. ${tax}% ${taxname}" - -#. Default: "Total incl. charges" -#: browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "Totaal incl. kosten" - -#. Default: "Total incl. charges and ${taxname}" -#: browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "Totaal incl. kosten en ${taxname}" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "Totaal incl. kosten and ${tax}% ${taxname}" - -#: content/variation.py:26 -msgid "Type" -msgstr "Type" - -#. Default: "Variations" -#: browser/variations.pt:25 -msgid "Variations" -msgstr "Varianten" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: browser/components/confirmation.pt:12 -msgid "" -"We successfully received your order. An Email has been sent to you " -"containing all the order details." -msgstr "" -"Uw bestelling is in goede orde ontvangen. Er is een e-mail naar u verstuurd " -"met de details van uw bestelling." - -#: browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "U hebt nog geen artikelen aan uw winkelmandje toegevoegd." - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: browser/cart.pt:108 -msgid "" -"You have to be registered to check out your order, either ${log_in} if you " -"already have an account or head over to the ${registration_form} if you " -"don't." -msgstr "" -"U kunt alleen bestellen als u bent ingelogd. ${log_in} als u al een account " -"heeft, of ga anders naar het ${registration_form}" - -#. Default: "Your shopping cart" -#: browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "Uw winkelmandje" - -#. Default: "Your shopping cart is empty" -#: browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "Uw winkelmandje is leeg" - -#. Default: "ZIP / City" -#: browser/address.pt:185 -msgid "ZIP / City" -msgstr "Postcode / Stad" - -#. Default: "Zone" -#: browser/address.pt:253 -msgid "Zone" -msgstr "Zone" - -#. Default: "add" -#: browser/configlet.pt:192 -msgid "add" -msgstr "toevoegen" - -#. Default: "add to cart" -#: browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "toevoegen aan winkelmandje" - -#. Default: "Check out" -#: browser/checkout.pt:15 -msgid "checkout_title" -msgstr "Bestellen" - -#. Default: "List of all orders and their statuses" -#: profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "Lijst van bestellingen en hun status" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: browser/images.pt:40 -msgid "description_no_images" -msgstr "" -"Dit artikel heeft geen afbeeldingen. Om een afbeelding toe te voegen, klik " -"op de knop Toevoegen, of knip-en-plak een afbeelding van een andere plek." - -#. Default: "No orders were found." -#: browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "Geen bestellingen gevonden" - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" -"Dit artikel heeft geen prijzen. Om een prijs toe te voegen, klik op de knop " -"Toevoegen, of knip-en-plak een prijs van een andere plek." - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: content/variation.py:52 -msgid "description_price" -msgstr "" -"Als meerdere geselecteerde varianten in verschillende categoriën " -"verschillende prijzen hebben wordt de hoogste prijs gebruikt voor de prijs " -"van de geselecteerde combinatie." - -#. Default: "Shipment methods for this product" -#: content/product.py:68 -msgid "description_shipment_methods" -msgstr "Verzendingsmethoden voor dit artikel" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: order.py:475 -msgid "email_customer_body" -msgstr "" -"Geachte ${name},\n" -"\n" -"Uw bestelling is geplaatst. Hieronder vindt u een overzicht van uw " -"bestelling.\n" -"\n" -"Bestellingsnummer: ${orderid}\n" -"\n" -"${cart}\n" -"Valuta: ${currency}\n" -"\n" -"\n" -"Adres:\n" -"${address}\n" -"\n" -"Betaling:\n" -"${payment}\n" -"\n" -"Verzending:\n" -"${shipments}\n" -"\n" -"\n" -" Als u vragen hebt over uw bestelling, schroom dan niet om contact met ons " -"op te nemen op het adres ${from_email}.\n" -"\n" -" Met vriendelijke groet,\n" -"\n" -"${from_name}" - -#. Default: "Confirmation e-mail" -#: order.py:402 -msgid "email_customer_title" -msgstr "Bevestigingsmail" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: order.py:454 -msgid "email_order_body" -msgstr "" -"Nieuwe bestelling van ${name}\n" -"\n" -"Bestellingsnummer: ${orderid}\n" -"\n" -"${cart}\n" -"Valuta: ${currency}\n" -"\n" -"\n" -"Adres:\n" -"${address}\n" -"\n" -"Betaling:\n" -"${payment}\n" -"\n" -"Verzending:\n" -"${shipments}" - -#. Default: "New order [${orderid}]" -#: order.py:393 -msgid "email_order_title" -msgstr "Nieuwe bestelling [${orderid}]" - -#. Default: "general terms and conditions" -#: browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "Algemene voorwaarden" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: browser/images.pt:35 -msgid "info_Image" -msgstr "Dit zijn de afbeeldingen van een variant van artikel ${product}" - -#. Default: "You are currently looking at a variation of the product ${product}." -#: browser/variation.pt:25 -msgid "info_variation" -msgstr "Dit is een variant van artikel ${product}" - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "Dit zijn de prijzen van een variant van artikel ${product}" - -#. Default: "Address" -#: browser/orders.py:73 -msgid "label_address" -msgstr "Adres" - -#. Default: "Cancelled" -#: browser/orders.py:37 -msgid "label_cancelled" -msgstr "Geannuleerd" - -#. Default: "Currency" -#: browser/orders.py:59 -msgid "label_currency" -msgstr "Valuta" - -#. Default: "Date" -#: browser/orders.py:56 -msgid "label_date" -msgstr "Datum" - -#. Default: "Failed" -#: browser/orders.py:36 -msgid "label_failed" -msgstr "Mislukt" - -#. Default: "Initialized" -#: browser/orders.py:33 -msgid "label_initialized" -msgstr "Geinitialiseerd" - -#. Default: "Order id" -#: browser/orders.py:50 -msgid "label_order_id" -msgstr "Order nummer" - -#. Default: "Order status" -#: browser/orders.py:66 -msgid "label_order_state" -msgstr "Order status" - -#. Default: "Price total" -#: browser/orders.py:62 -msgid "label_price_total" -msgstr "Totale prijs" - -#. Default: "Processed" -#: browser/orders.py:35 -msgid "label_processed" -msgstr "Verwerkt" - -#. Default: "Products" -#: browser/orders.py:77 -msgid "label_products" -msgstr "Artikelen" - -#. Default: "Sent" -#: browser/orders.py:34 -msgid "label_sent" -msgstr "Verzonden" - -#. Default: "Shipment methods" -#: content/product.py:67 -msgid "label_shipment_methods" -msgstr "Verzendmethodes" - -#. Default: "Shipment id's" -#: browser/orders.py:81 -msgid "label_shipmentids" -msgstr "Zending nummer" - -#. Default: "User id" -#: browser/orders.py:53 -msgid "label_user_id" -msgstr "Gebruikers id" - -#. Default: "Zone" -#: browser/orders.py:69 -msgid "label_zone" -msgstr "Gebied" - -#. Default: "log in" -#: browser/cart.pt:101 -msgid "log_in" -msgstr "Log in" - -#. Default: "Check out canceled" -#: browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "Bestelling geannuleerd" - -#. Default: "Check out failed" -#: browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "Bestelling mislukt" - -#. Default: "${offer} instead of ${price}" -#: browser/macros.pt:11 -msgid "price_offer" -msgstr "${offer} in plaats van ${price}" - -#. Default: "registration form" -#: browser/cart.pt:108 -msgid "registration_form" -msgstr "aanmeldformulier" - -#. Default: "remove" -#: browser/configlet.pt:168 -msgid "remove" -msgstr "verwijder" - -#. Default: "Please supply an order id." -#: browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "Geef een ordernummer" - -#. Default: "Please check the order id." -#: browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "" - -#. Default: "Manage orders" -#: browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "Bestellingen beheren" - -#. Default: "Which one?" -#: browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "Welke?" - -#. Default: "Order details" -#: browser/order_details.pt:17 -msgid "title_order_details" -msgstr "Order details" - -#. Default: "The order could not be found." -#: browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "Order werd niet gevonden." diff --git a/pcommerce/core/locales/nl/LC_MESSAGES/plone.po b/pcommerce/core/locales/nl/LC_MESSAGES/plone.po deleted file mode 100644 index 01d631d..0000000 --- a/pcommerce/core/locales/nl/LC_MESSAGES/plone.po +++ /dev/null @@ -1,52 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2011-08-31 15:40+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" -"Last-Translator: Albert Peschar \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: nl\n" -"Language-Name: Nederlands\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: plone\n" - -msgid "Price" -msgstr "Prijs" - -msgid "A price" -msgstr "Een prijs" - -msgid "Product" -msgstr "Artikel" - -msgid "A product" -msgstr "Een artikel" - -msgid "Variation" -msgstr "Variant" - -msgid "A variation of a product" -msgstr "Een variant van een artikel" - -msgid "Variations" -msgstr "Varianten" - -msgid "Prices" -msgstr "Prijzen" - -msgid "PCommerce configuration" -msgstr "PCommerce-instellingen" - -msgid "Shop" -msgstr "Winkel" - -msgid "ShopFolder" -msgstr "Winkel-Map" - -msgid "Images" -msgstr "Afbeeldingen" diff --git a/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po b/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po deleted file mode 100644 index 9af0626..0000000 --- a/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po +++ /dev/null @@ -1,752 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: 2011-11-18 10:41+0100\n" -"Last-Translator: Espen Moe-Nilssen \n" -"Language-Team: Espen Moe-Nilssen \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: no\n" -"Language-Name: Norwegian bokmål\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: plone\n" -"X-Poedit-Language: Norwegian Bokmal\n" -"X-Poedit-Country: NORWAY\n" - -#. Default: "Add image" -#: browser/images.pt:23 -msgid "Add image" -msgstr "Legg til bilde" - -#. Default: "Add price" -#: browser/prices.pt:24 -msgid "Add price" -msgstr "Legg til pris" - -#. Default: "Add variation" -#: browser/variations.pt:22 -msgid "Add variation" -msgstr "Legg til variant" - -#: browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "${count} lagt til i handlekurven" - -#: browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "Produkt lagt til i handlekurv" - -#: content/variation.py:35 -msgid "Additional price" -msgstr "Ekstra pris" - -#. Default: "Additional prices" -#: browser/prices.pt:27 -msgid "Additional prices" -msgstr "Ekstra priser" - -#: steps.py:10 -msgid "Address" -msgstr "Adresse" - -#. Default: "Address 1" -#: browser/address.pt:139 -msgid "Address 1" -msgstr "Adresse 1" - -#. Default: "Address 2" -#: browser/address.pt:166 -msgid "Address 2" -msgstr "Adresse 2" - -#. Default: "Amount" -#: browser/cart.pt:42 -msgid "Amount" -msgstr "Sum" - -#. Default: "Billing address" -#: browser/components/address.pt:12 -msgid "Billing address" -msgstr "Fakturaadresse" - -#: browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "Avbryt bestilling" - -#. Default: "Check out" -#: browser/cart.pt:34 -msgid "Check out" -msgstr "Bestille" - -#. Default: "Company" -#: browser/address.pt:120 -msgid "Company" -msgstr "Firma" - -#. Default: "Confirmation" -#: browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "Bekreftelse" - -#: browser/checkout.py:255 -msgid "Continue shopping" -msgstr "Fortsette å handle" - -#. Default: "Country" -#: browser/address.pt:224 -msgid "Country" -msgstr "Land" - -#. Default: "Edit cart" -#: browser/cart.pt:120 -msgid "Edit cart" -msgstr "Rediger handlekurv" - -#. Default: "Email" -#: browser/address.pt:294 -msgid "Email" -msgstr "E.post" - -#. Default: "Email address" -#: browser/configlet.pt:116 -#, fuzzy -msgid "Email address" -msgstr "Fakturaadresse" - -#. Default: "First name" -#: browser/address.pt:64 -msgid "First name" -msgstr "Fornavn" - -#. Default: "GTC" -#: browser/configlet.pt:68 -msgid "GTC" -msgstr "Generelle vilkår" - -#: content/product.py:59 -msgid "Hot product" -msgstr "Populært produkt" - -#. Default: "I accept the ${link}" -#: browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "Jeg godtar ${link}" - -#. Default: "Image" -#: browser/images.pt:63 -msgid "Image" -msgstr "Bilde" - -#. Default: "Images" -#: browser/images.pt:26 -msgid "Images" -msgstr "Bilder" - -#. Default: "Last name" -#: browser/address.pt:92 -msgid "Last name" -msgstr "Etternavn" - -#. Default: "Manage orders" -#: profiles/default/actions.xml -msgid "Manage orders" -msgstr "Administrere bestillinger" - -#. Default: "Mr." -#: browser/address.pt:46 -msgid "Mr." -msgstr "Hr." - -#. Default: "Mrs. / Ms." -#: browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "Ms." - -#: content/product.py:51 -msgid "New product" -msgstr "Nytt produkt" - -#. Default: "New products in our shop" -#: browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "Nytt produkt hos oss" - -#: browser/checkout.py:258 -msgid "Next step" -msgstr "Neste steg" - -#: browser/orders.py:110 -msgid "No" -msgstr "Produktnummer" - -#. Default: "No of articles:" -#: browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "Antall produkter:" - -#. Default: "Overview" -#: browser/components/overview.pt:9 -msgid "Overview" -msgstr "Oversikt" - -#. Default: "PCommerce configuration" -#: browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "PCommerce-instillinger" - -#. Default: "Payment" -#: browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "Betaling" - -#: browser/checkout.py:331 -msgid "Payment canceled" -msgstr "Betaling avbrutt" - -#: browser/checkout.py:316 -msgid "Payment failed" -msgstr "Betaling mislykkes" - -#. Default: "Phone" -#: browser/address.pt:322 -msgid "Phone" -msgstr "Telefon" - -#: browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "Vennligst skriv inn et desimalnummer (f.eks 7,6)" - -#: browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "Vennligst oppgi skattenavn" - -#: browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "Vennligst skriv inn sone navn" - -#: browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "Velg betalingsmåte" - -#: browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "Velg forsendelsesmåte" - -#: browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "Velg en variant" - -#: browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "Skriv inn mengde" - -#. Default: "Post checkout" -#: browser/configlet.pt:92 -msgid "Post checkout" -msgstr "Side etter bestilling" - -#: browser/checkout.py:247 -msgid "Previous step" -msgstr "Forige steg" - -#. Default: "Price" -#: browser/cart.pt:43 -msgid "Price" -msgstr "Pris" - -#. Default: "Price total" -#: browser/cart.pt:44 -msgid "Price total" -msgstr "Totalpris" - -#: browser/checkout.py:246 -msgid "Print" -msgstr "Skriv ut" - -#. Default: "Product" -#: browser/cart.pt:41 -msgid "Product" -msgstr "Produkt" - -#. Default: "Product highlights" -#: browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "Aktuelle artikler" - -#. Default: "Product variations" -#: browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "Produktvariant" - -#. Default: "Productname" -#: browser/configlet.pt:36 -msgid "Productname" -msgstr "Produktnavn" - -#. Default: "Related products" -#: browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "Relative produkter" - -#. Default: "Remove" -#: browser/cart.pt:45 -msgid "Remove" -msgstr "Slett" - -#: browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "${count} produkter fjernet fra handlekurven" - -#: browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "Fjernet produktet fra handlekurv" - -#. Default: "Salutation" -#: browser/address.pt:35 -msgid "Salutation" -msgstr "Tittel" - -#. Default: "Select the desired payment method" -#: browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "Velg betalingsmetode" - -#. Default: "Select the desired shipment method" -#: browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "Velg forsendelsesmåte" - -#. Default: "Select the desired shipment method for the following products:" -#: browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "Velg forsendelsesmåte for følgende produkter:" - -#: browser/checkout.py:257 -msgid "Send order" -msgstr "bestillingen er sendt" - -#. Default: "Shipment" -#: browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "Forsending" - -#: browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "Handlekurv" - -#. Default: "Tax factor" -#: browser/configlet.pt:145 -msgid "Tax factor" -msgstr "Skatteprosent" - -#. Default: "Tax included in product price" -#: browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "Skatt er inkludert i produktprisen" - -#. Default: "Tax name" -#: browser/configlet.pt:144 -msgid "Tax name" -msgstr "Skattenavn" - -#. Default: "Taxes" -#: browser/configlet.pt:138 -msgid "Taxes" -msgstr "Skatter" - -#. Default: "Thank you!" -#: browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "Takk!" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "" - -#: browser/components/gtc.py:17 -msgid "" -"The general terms and conditions have to be accepted to finish your check " -"out." -msgstr "Generelle vilkår må godtas før bestilling kan sendes" - -#. Default: "The name appearing in payment-terminals" -#: browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "Navnet som vises i betalings-terminaler" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: browser/configlet.pt:73 -msgid "" -"The path to the page holding the general terms and conditions to accept " -"before payment" -msgstr "Nettverksbanen til siden med de generelle vilkårene etc." - -#. Default: "The path to the page to be redirected to after checkout" -#: browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "Nettverksstien til siden en blir omdirigert til etter kassen" - -#. Default: "Total" -#: browser/cart.pt:78 -msgid "Total" -msgstr "Total" - -#. Default: "Total ${currency}:" -#: browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "Totalt ${currency}:" - -#. Default: "Total incl. ${taxname}" -#: browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "Totalt inkl. ${taxname}" - -#: order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "Totalt inkl. ${tax}% ${taxname}" - -#. Default: "Total incl. charges" -#: browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "Totalt inkl. kostnader" - -#. Default: "Total incl. charges and ${taxname}" -#: browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "Totalt inkl. kostnader og ${taxname}" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "Totalt inkl. kostnader og ${tax}% ${taxname}" - -#: content/variation.py:26 -msgid "Type" -msgstr "Type" - -#. Default: "Variations" -#: browser/variations.pt:25 -msgid "Variations" -msgstr "Varianter" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: browser/components/confirmation.pt:12 -msgid "" -"We successfully received your order. An Email has been sent to you " -"containing all the order details." -msgstr "" -"Vi har mottatt din bestilling. En e-post har blitt sendt til deg som " -"inneholder alle ordredetaljer." - -#: browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "Du har ennå ikke lagt til noen produkter i handlekurven din" - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: browser/cart.pt:108 -msgid "" -"You have to be registered to check out your order, either ${log_in} if you " -"already have an account or head over to the ${registration_form} if you " -"don't." -msgstr "" -"Du må være registrert for å sjekke ut din bestilling, enten ${log_in} hvis " -"du allerede har en konto eller gå over til ${registration_form} hvis ikke." - -#. Default: "Your shopping cart" -#: browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "Din handlekurv" - -#. Default: "Your shopping cart is empty" -#: browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "Handlevognen er tom" - -#. Default: "ZIP / City" -#: browser/address.pt:185 -msgid "ZIP / City" -msgstr "Postkode / Sted" - -#. Default: "Zone" -#: browser/address.pt:253 -msgid "Zone" -msgstr "Sone" - -#. Default: "add" -#: browser/configlet.pt:192 -msgid "add" -msgstr "legg til" - -#. Default: "add to cart" -#: browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "legg i handlekurv" - -#. Default: "Check out" -#: browser/checkout.pt:15 -msgid "checkout_title" -msgstr "Bestille" - -#. Default: "List of all orders and their statuses" -#: profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "Liste over alle ordrer og deres status" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: browser/images.pt:40 -msgid "description_no_images" -msgstr "" -"Dette produktet har ingen bilder. For å legge til et bilde, trykker du på " -"knappen Legg til, eller limer inn innhold fra et annet sted." - -#. Default: "No orders were found." -#: browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "Ingen bestillinger ble funnet." - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" -"Dette produktet har ingen ytterligere priser. For å legge til en pris, trykk " -"på knappen Legg til, eller lim inn innhold fra et annet sted." - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: content/variation.py:52 -msgid "description_price" -msgstr "" -"Hvis flere valgte variasjoner i ulike kategorier har enhetspriser, vil " -"større prisen bli regnskapsført i prisingen av den valgte kombinasjonen" - -#. Default: "Shipment methods for this product" -#: content/product.py:68 -msgid "description_shipment_methods" -msgstr "Forsendelsemetoder for dette produktet" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: order.py:475 -msgid "email_customer_body" -msgstr "" -"Kjære ${name} \n" -"\n" -"Bestillingen har med hell blitt registrert. Vennligst finne en komplett \n" -"oversikt over bestillingen din nedenfor. \n" -"\n" -"Order ID: ${orderid} \n" -"\n" -"${cart} \n" -"Valuta: ${currency} \n" -"\n" -"\n" -"Adresse: \n" -"${address} \n" -"\n" -"Betaling: \n" -"${payment} \n" -"\n" -"Forsendelse: \n" -"${shipments} \n" -"\n" -"\n" -"Hvis du har spørsmål angående kjøpet ikke nøl \n" -"å kontakte oss på ${from_email}. \n" -"\n" -"Beste hilsen \n" -"\n" -"${from_name}" - -#. Default: "Confirmation e-mail" -#: order.py:402 -msgid "email_customer_title" -msgstr "Bekreftelses-epost" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: order.py:454 -msgid "email_order_body" -msgstr "" -"Ny ordre av ${name} \n" -"\n" -"OrdreID: ${orderid} \n" -"\n" -"${cart} \n" -"Valuta: ${currency} \n" -"\n" -"\n" -"Adresse: \n" -"${address} \n" -"\n" -"Betaling: \n" -"${payment} \n" -"\n" -"Forsendelse: \n" -"${shipments}" - -#. Default: "New order [${orderid}]" -#: order.py:393 -msgid "email_order_title" -msgstr "Ny bestilling [${orderid}]" - -#. Default: "general terms and conditions" -#: browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "Generelle vilkår" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: browser/images.pt:35 -msgid "info_Image" -msgstr "Du er nå ser på bilder for en variant av produktet ${product}." - -#. Default: "You are currently looking at a variation of the product ${product}." -#: browser/variation.pt:25 -msgid "info_variation" -msgstr "Du ser for øyeblikket på en variant av produktet ${product}." - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "Du er nå ser på prisene for en variant av produktet ${product}." - -#. Default: "Address" -#: browser/orders.py:73 -msgid "label_address" -msgstr "Adresse" - -#. Default: "Cancelled" -#: browser/orders.py:37 -msgid "label_cancelled" -msgstr "Avbrutt" - -#. Default: "Currency" -#: browser/orders.py:59 -msgid "label_currency" -msgstr "Valuta" - -#. Default: "Date" -#: browser/orders.py:56 -msgid "label_date" -msgstr "Dato" - -#. Default: "Failed" -#: browser/orders.py:36 -msgid "label_failed" -msgstr "Mislykket" - -#. Default: "Initialized" -#: browser/orders.py:33 -msgid "label_initialized" -msgstr "Initialisert" - -#. Default: "Order id" -#: browser/orders.py:50 -msgid "label_order_id" -msgstr "Ordrenummer" - -#. Default: "Order status" -#: browser/orders.py:66 -msgid "label_order_state" -msgstr "Ordrestatus" - -#. Default: "Price total" -#: browser/orders.py:62 -msgid "label_price_total" -msgstr "Totalpris" - -#. Default: "Processed" -#: browser/orders.py:35 -msgid "label_processed" -msgstr "Fortsett" - -#. Default: "Products" -#: browser/orders.py:77 -msgid "label_products" -msgstr "Produkter" - -#. Default: "Sent" -#: browser/orders.py:34 -msgid "label_sent" -msgstr "Sendt" - -#. Default: "Shipment methods" -#: content/product.py:67 -msgid "label_shipment_methods" -msgstr "Forsendelsesmetode" - -#. Default: "Shipment id's" -#: browser/orders.py:81 -msgid "label_shipmentids" -msgstr "Sendingsnummer" - -#. Default: "User id" -#: browser/orders.py:53 -msgid "label_user_id" -msgstr "Brukerid" - -#. Default: "Zone" -#: browser/orders.py:69 -msgid "label_zone" -msgstr "Sone" - -#. Default: "log in" -#: browser/cart.pt:101 -msgid "log_in" -msgstr "Logg inn" - -#. Default: "Check out canceled" -#: browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "Bestilling avbrutt" - -#. Default: "Check out failed" -#: browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "Bestilling mislykkes" - -#. Default: "${offer} instead of ${price}" -#: browser/macros.pt:11 -msgid "price_offer" -msgstr "${offer} i stedet for ${price}" - -#. Default: "registration form" -#: browser/cart.pt:108 -msgid "registration_form" -msgstr "Søknadsskjema" - -#. Default: "remove" -#: browser/configlet.pt:168 -msgid "remove" -msgstr "slett" - -#. Default: "Please supply an order id." -#: browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "Angi et ordrenummer" - -#. Default: "Please check the order id." -#: browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "Vennligst sjekk ordreID" - -#. Default: "Manage orders" -#: browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "Behandle ordrer" - -#. Default: "Which one?" -#: browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "Hvilken?" - -#. Default: "Order details" -#: browser/order_details.pt:17 -msgid "title_order_details" -msgstr "Ordredetaljer" - -#. Default: "The order could not be found." -#: browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "Ordren ble ikke funnet" diff --git a/pcommerce/core/locales/no/LC_MESSAGES/plone.po b/pcommerce/core/locales/no/LC_MESSAGES/plone.po deleted file mode 100644 index b3b9701..0000000 --- a/pcommerce/core/locales/no/LC_MESSAGES/plone.po +++ /dev/null @@ -1,56 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: pcommerce.core\n" -"POT-Creation-Date: 2011-08-31 15:40+0000\n" -"PO-Revision-Date: 2011-11-17 13:30+0100\n" -"Last-Translator: Espen Moe-Nilssen \n" -"Language-Team: Espen Moe-Nilssen \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: no\n" -"Language-Name: Norwegian bokmål\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: plone\n" -"X-Poedit-Language: Norwegian Bokmal\n" -"X-Poedit-Country: NORWAY\n" - -msgid "Price" -msgstr "Pris" - -msgid "A price" -msgstr "En pris" - -msgid "Product" -msgstr "Produkt" - -msgid "A product" -msgstr "Et produkt" - -msgid "Variation" -msgstr "Variant" - -msgid "A variation of a product" -msgstr "En variant av produktet" - -msgid "Variations" -msgstr "Varianter" - -msgid "Prices" -msgstr "Priser" - -msgid "PCommerce configuration" -msgstr "PCommerce-instillinger" - -msgid "Shop" -msgstr "Butikk" - -msgid "ShopFolder" -msgstr "Butikkfolder" - -msgid "Images" -msgstr "Bilder" - - diff --git a/pcommerce/core/locales/pcommerce.pot b/pcommerce/core/locales/pcommerce.pot deleted file mode 100644 index cdd7ca3..0000000 --- a/pcommerce/core/locales/pcommerce.pot +++ /dev/null @@ -1,690 +0,0 @@ -# --- PLEASE EDIT THE LINES BELOW CORRECTLY --- -# SOME DESCRIPTIVE TITLE. -# FIRST AUTHOR , YEAR. -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2012-02-06 08:30+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: en\n" -"Language-Name: English\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: pcommerce\n" - -#. Default: "Add image" -#: ./browser/images.pt:23 -msgid "Add image" -msgstr "" - -#. Default: "Add price" -#: ./browser/prices.pt:24 -msgid "Add price" -msgstr "" - -#. Default: "Add variation" -#: ./browser/variations.pt:22 -msgid "Add variation" -msgstr "" - -#: ./browser/viewlets/processor.py:46 -msgid "Added ${count} items to cart" -msgstr "" - -#: ./browser/viewlets/processor.py:48 -msgid "Added item to cart" -msgstr "" - -#: ./content/variation.py:35 -msgid "Additional price" -msgstr "" - -#. Default: "Additional prices" -#: ./browser/prices.pt:27 -msgid "Additional prices" -msgstr "" - -#: ./steps.py:10 -msgid "Address" -msgstr "" - -#. Default: "Address 1" -#: ./browser/address.pt:139 -msgid "Address 1" -msgstr "" - -#. Default: "Address 2" -#: ./browser/address.pt:166 -msgid "Address 2" -msgstr "" - -#. Default: "Amount" -#: ./browser/cart.pt:42 -msgid "Amount" -msgstr "" - -#. Default: "Billing address" -#: ./browser/components/address.pt:12 -msgid "Billing address" -msgstr "" - -#: ./browser/checkout.py:265 -msgid "Cancel checkout" -msgstr "" - -#. Default: "Check out" -#: ./browser/cart.pt:34 -msgid "Check out" -msgstr "" - -#. Default: "Company" -#: ./browser/address.pt:120 -msgid "Company" -msgstr "" - -#. Default: "Confirmation" -#: ./browser/components/confirmation.pt:17 -msgid "Confirmation" -msgstr "" - -#: ./browser/checkout.py:255 -msgid "Continue shopping" -msgstr "" - -#. Default: "Country" -#: ./browser/address.pt:224 -msgid "Country" -msgstr "" - -#. Default: "Edit cart" -#: ./browser/cart.pt:120 -msgid "Edit cart" -msgstr "" - -#. Default: "Email" -#: ./browser/address.pt:294 -msgid "Email" -msgstr "" - -#. Default: "Email address" -#: ./browser/configlet.pt:116 -msgid "Email address" -msgstr "" - -#. Default: "First name" -#: ./browser/address.pt:64 -msgid "First name" -msgstr "" - -#. Default: "GTC" -#: ./browser/configlet.pt:68 -msgid "GTC" -msgstr "" - -#: ./content/product.py:59 -msgid "Hot product" -msgstr "" - -#. Default: "I accept the ${link}" -#: ./browser/components/gtc.pt:17 -msgid "I accept the ${link}" -msgstr "" - -#. Default: "Image" -#: ./browser/images.pt:63 -msgid "Image" -msgstr "" - -#. Default: "Images" -#: ./browser/images.pt:26 -msgid "Images" -msgstr "" - -#. Default: "Last name" -#: ./browser/address.pt:92 -msgid "Last name" -msgstr "" - -#. Default: "Manage orders" -#: ./profiles/default/actions.xml -msgid "Manage orders" -msgstr "" - -#. Default: "Mr." -#: ./browser/address.pt:46 -msgid "Mr." -msgstr "" - -#. Default: "Mrs. / Ms." -#: ./browser/address.pt:52 -msgid "Mrs. / Ms." -msgstr "" - -#: ./content/product.py:51 -msgid "New product" -msgstr "" - -#. Default: "New products in our shop" -#: ./browser/viewlets/new.pt:2 -msgid "New products in our shop" -msgstr "" - -#: ./browser/checkout.py:258 -msgid "Next step" -msgstr "" - -#: ./browser/orders.py:110 -msgid "No" -msgstr "" - -#. Default: "No of articles:" -#: ./browser/portlets/cart.pt:18 -msgid "No of articles:" -msgstr "" - -#. Default: "Overview" -#: ./browser/components/overview.pt:9 -msgid "Overview" -msgstr "" - -#. Default: "PCommerce configuration" -#: ./browser/configlet.pt:13 -msgid "PCommerce configuration" -msgstr "" - -#. Default: "Payment" -#: ./browser/components/confirmation.pt:48 -msgid "Payment" -msgstr "" - -#: ./browser/checkout.py:331 -msgid "Payment canceled" -msgstr "" - -#: ./browser/checkout.py:316 -msgid "Payment failed" -msgstr "" - -#. Default: "Phone" -#: ./browser/address.pt:322 -msgid "Phone" -msgstr "" - -#: ./browser/configlet.py:43 -msgid "Please enter a floating point number (e.g. 7.6)" -msgstr "" - -#: ./browser/configlet.py:39 -msgid "Please provide a tax name" -msgstr "" - -#: ./browser/configlet.py:37 -msgid "Please provide a zone name" -msgstr "" - -#: ./browser/components/payments.py:17 -msgid "Please select a payment method." -msgstr "" - -#: ./browser/components/shipments.py:25 -msgid "Please select a shipment method." -msgstr "" - -#: ./browser/viewlets/processor.py:29 -msgid "Please select a variation" -msgstr "" - -#: ./browser/viewlets/processor.py:17 -msgid "Please specify an amount" -msgstr "" - -#. Default: "Post checkout" -#: ./browser/configlet.pt:92 -msgid "Post checkout" -msgstr "" - -#: ./browser/checkout.py:247 -msgid "Previous step" -msgstr "" - -#. Default: "Price" -#: ./browser/cart.pt:43 -msgid "Price" -msgstr "" - -#. Default: "Price total" -#: ./browser/cart.pt:44 -msgid "Price total" -msgstr "" - -#: ./browser/checkout.py:246 -msgid "Print" -msgstr "" - -#. Default: "Product" -#: ./browser/cart.pt:41 -msgid "Product" -msgstr "" - -#. Default: "Product highlights" -#: ./browser/viewlets/hot.pt:2 -msgid "Product highlights" -msgstr "" - -#. Default: "Product variations" -#: ./browser/viewlets/variation.pt:2 -msgid "Product variations" -msgstr "" - -#. Default: "Productname" -#: ./browser/configlet.pt:36 -msgid "Productname" -msgstr "" - -#. Default: "Related products" -#: ./browser/viewlets/related.pt:2 -msgid "Related products" -msgstr "" - -#. Default: "Remove" -#: ./browser/cart.pt:45 -msgid "Remove" -msgstr "" - -#: ./browser/viewlets/processor.py:50 -msgid "Removed ${count} items from cart" -msgstr "" - -#: ./browser/viewlets/processor.py:52 -msgid "Removed item from cart" -msgstr "" - -#. Default: "Salutation" -#: ./browser/address.pt:35 -msgid "Salutation" -msgstr "" - -#. Default: "Select the desired payment method" -#: ./browser/components/payments.pt:12 -msgid "Select the desired payment method" -msgstr "" - -#. Default: "Select the desired shipment method" -#: ./browser/components/shipments.pt:13 -msgid "Select the desired shipment method" -msgstr "" - -#. Default: "Select the desired shipment method for the following products:" -#: ./browser/components/shipments.pt:54 -msgid "Select the desired shipment method for the following products:" -msgstr "" - -#: ./browser/checkout.py:257 -msgid "Send order" -msgstr "" - -#. Default: "Shipment" -#: ./browser/components/confirmation.pt:30 -msgid "Shipment" -msgstr "" - -#: ./browser/portlets/cart.py:23 -msgid "Shopping cart" -msgstr "" - -#. Default: "Tax factor" -#: ./browser/configlet.pt:145 -msgid "Tax factor" -msgstr "" - -#. Default: "Tax included in product price" -#: ./browser/configlet.pt:206 -msgid "Tax included in product price" -msgstr "" - -#. Default: "Tax name" -#: ./browser/configlet.pt:144 -msgid "Tax name" -msgstr "" - -#. Default: "Taxes" -#: ./browser/configlet.pt:138 -msgid "Taxes" -msgstr "" - -#. Default: "Thank you!" -#: ./browser/components/confirmation.pt:9 -msgid "Thank you!" -msgstr "" - -#. Default: "The email address receiving and sending pcommerce related emails" -#: ./browser/configlet.pt:121 -msgid "The email address receiving and sending pcommerce related emails" -msgstr "" - -#: ./browser/components/gtc.py:17 -msgid "The general terms and conditions have to be accepted to finish your check out." -msgstr "" - -#. Default: "The name appearing in payment-terminals" -#: ./browser/configlet.pt:49 -msgid "The name appearing in payment-terminals" -msgstr "" - -#. Default: "The path to the page holding the general terms and conditions to accept before payment" -#: ./browser/configlet.pt:73 -msgid "The path to the page holding the general terms and conditions to accept before payment" -msgstr "" - -#. Default: "The path to the page to be redirected to after checkout" -#: ./browser/configlet.pt:97 -msgid "The path to the page to be redirected to after checkout" -msgstr "" - -#. Default: "Total" -#: ./browser/cart.pt:78 -msgid "Total" -msgstr "" - -#. Default: "Total ${currency}:" -#: ./browser/portlets/cart.pt:20 -msgid "Total ${currency}:" -msgstr "" - -#. Default: "Total incl. ${taxname}" -#: ./browser/macros.pt:158 -msgid "Total incl. ${taxname}" -msgstr "" - -#: ./order.py:341 -msgid "Total incl. ${tax}% ${taxname}" -msgstr "" - -#. Default: "Total incl. charges" -#: ./browser/macros.pt:131 -msgid "Total incl. charges" -msgstr "" - -#. Default: "Total incl. charges and ${taxname}" -#: ./browser/macros.pt:187 -msgid "Total incl. charges and ${taxname}" -msgstr "" - -#. Default: "Total incl. charges and ${tax}% ${taxname}" -#: ./browser/macros.pt:190 -msgid "Total incl. charges and ${tax}% ${taxname}" -msgstr "" - -#: ./content/variation.py:26 -msgid "Type" -msgstr "" - -#. Default: "Variations" -#: ./browser/variations.pt:25 -msgid "Variations" -msgstr "" - -#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." -#: ./browser/components/confirmation.pt:12 -msgid "We successfully received your order. An Email has been sent to you containing all the order details." -msgstr "" - -#: ./browser/checkout.py:43 -msgid "You have not yet added any products to your cart" -msgstr "" - -#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -#: ./browser/cart.pt:108 -msgid "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." -msgstr "" - -#. Default: "Your shopping cart" -#: ./browser/cart.pt:16 -msgid "Your shopping cart" -msgstr "" - -#. Default: "Your shopping cart is empty" -#: ./browser/cart.pt:20 -msgid "Your shopping cart is empty" -msgstr "" - -#. Default: "ZIP / City" -#: ./browser/address.pt:185 -msgid "ZIP / City" -msgstr "" - -#. Default: "Zone" -#: ./browser/address.pt:253 -msgid "Zone" -msgstr "" - -#. Default: "add" -#: ./browser/configlet.pt:192 -msgid "add" -msgstr "" - -#. Default: "add to cart" -#: ./browser/viewlets/buy.pt:19 -msgid "add to cart" -msgstr "" - -#. Default: "Check out" -#: ./browser/checkout.pt:15 -msgid "checkout_title" -msgstr "" - -#. Default: "List of all orders and their statuses" -#: ./profiles/default/actions.xml -msgid "description_manage_orders" -msgstr "" - -#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." -#: ./browser/images.pt:40 -msgid "description_no_images" -msgstr "" - -#. Default: "No orders were found." -#: ./browser/manage_orders.pt:17 -msgid "description_no_orders" -msgstr "" - -#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." -#: ./browser/prices.pt:41 -msgid "description_no_prices" -msgstr "" - -#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." -#: ./content/variation.py:52 -msgid "description_price" -msgstr "" - -#. Default: "Shipment methods for this product" -#: ./content/product.py:68 -msgid "description_shipment_methods" -msgstr "" - -#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" -#: ./order.py:475 -msgid "email_customer_body" -msgstr "" - -#. Default: "Confirmation e-mail" -#: ./order.py:402 -msgid "email_customer_title" -msgstr "" - -#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" -#: ./order.py:454 -msgid "email_order_body" -msgstr "" - -#. Default: "New order [${orderid}]" -#: ./order.py:393 -msgid "email_order_title" -msgstr "" - -#. Default: "general terms and conditions" -#: ./browser/components/gtc.pt:17 -msgid "general terms and conditions" -msgstr "" - -#. Default: "You are currently looking at the images of a variation of the product ${product}." -#: ./browser/images.pt:35 -msgid "info_Image" -msgstr "" - -#. Default: "You are currently looking at a variation of the product ${product}." -#: ./browser/variation.pt:25 -msgid "info_variation" -msgstr "" - -#. Default: "You are currently looking at the prices of a variation of the product ${product}." -#: ./browser/prices.pt:36 -msgid "info_variation_prices" -msgstr "" - -#. Default: "Address" -#: ./browser/orders.py:73 -msgid "label_address" -msgstr "" - -#. Default: "Cancelled" -#: ./browser/orders.py:37 -msgid "label_cancelled" -msgstr "" - -#. Default: "Currency" -#: ./browser/orders.py:59 -msgid "label_currency" -msgstr "" - -#. Default: "Date" -#: ./browser/orders.py:56 -msgid "label_date" -msgstr "" - -#. Default: "Failed" -#: ./browser/orders.py:36 -msgid "label_failed" -msgstr "" - -#. Default: "Initialized" -#: ./browser/orders.py:33 -msgid "label_initialized" -msgstr "" - -#. Default: "Order id" -#: ./browser/orders.py:50 -msgid "label_order_id" -msgstr "" - -#. Default: "Order status" -#: ./browser/orders.py:66 -msgid "label_order_state" -msgstr "" - -#. Default: "Price total" -#: ./browser/orders.py:62 -msgid "label_price_total" -msgstr "" - -#. Default: "Processed" -#: ./browser/orders.py:35 -msgid "label_processed" -msgstr "" - -#. Default: "Products" -#: ./browser/orders.py:77 -msgid "label_products" -msgstr "" - -#. Default: "Sent" -#: ./browser/orders.py:34 -msgid "label_sent" -msgstr "" - -#. Default: "Shipment methods" -#: ./content/product.py:67 -msgid "label_shipment_methods" -msgstr "" - -#. Default: "Shipment id's" -#: ./browser/orders.py:81 -msgid "label_shipmentids" -msgstr "" - -#. Default: "User id" -#: ./browser/orders.py:53 -msgid "label_user_id" -msgstr "" - -#. Default: "Zone" -#: ./browser/orders.py:69 -msgid "label_zone" -msgstr "" - -#. Default: "log in" -#: ./browser/cart.pt:101 -msgid "log_in" -msgstr "" - -#. Default: "Check out canceled" -#: ./browser/checkout.py:359 -msgid "message_checkout_canceled" -msgstr "" - -#. Default: "Check out failed" -#: ./browser/checkout.py:373 -msgid "message_checkout_failed" -msgstr "" - -#. Default: "${offer} instead of ${price}" -#: ./browser/macros.pt:11 -msgid "price_offer" -msgstr "" - -#. Default: "registration form" -#: ./browser/cart.pt:108 -msgid "registration_form" -msgstr "" - -#. Default: "remove" -#: ./browser/configlet.pt:168 -msgid "remove" -msgstr "" - -#. Default: "Please supply an order id." -#: ./browser/order_details.pt:23 -msgid "text_no_order_id_supplied" -msgstr "" - -#. Default: "Please check the order id." -#: ./browser/order_details.pt:30 -msgid "text_order_not_found" -msgstr "" - -#. Default: "Manage orders" -#: ./browser/manage_orders.pt:13 -msgid "title_manage_orders" -msgstr "" - -#. Default: "Which one?" -#: ./browser/order_details.pt:21 -msgid "title_no_order_id_supplied" -msgstr "" - -#. Default: "Order details" -#: ./browser/order_details.pt:17 -msgid "title_order_details" -msgstr "" - -#. Default: "The order could not be found." -#: ./browser/order_details.pt:28 -msgid "title_order_not_found" -msgstr "" - diff --git a/pcommerce/core/locales/plone.pot b/pcommerce/core/locales/plone.pot deleted file mode 100644 index 58ccd22..0000000 --- a/pcommerce/core/locales/plone.pot +++ /dev/null @@ -1,51 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2010-12-15 08:16+0000\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0\n" -"Language-Code: en\n" -"Language-Name: English\n" -"Preferred-Encodings: utf-8 latin1\n" -"Domain: plone\n" - -msgid "Price" -msgstr "" - -msgid "A price" -msgstr "" - -msgid "Product" -msgstr "" - -msgid "A product" -msgstr "" - -msgid "Variation" -msgstr "" - -msgid "A variation of a product" -msgstr "" - -msgid "Variations" -msgstr "" - -msgid "Prices" -msgstr "" - -msgid "PCommerce configuration" -msgstr "" - -msgid "Shop" -msgstr "" - -msgid "ShopFolder" -msgstr "" - -msgid "Images" -msgstr "" diff --git a/pcommerce/core/order.py b/pcommerce/core/order.py deleted file mode 100644 index 97c3797..0000000 --- a/pcommerce/core/order.py +++ /dev/null @@ -1,569 +0,0 @@ -import transaction -from time import time - -from BTrees.OOBTree import OOBTree -from persistent import Persistent -from persistent.list import PersistentList -from persistent.mapping import PersistentMapping - -from zope.event import notify -from zope.i18n import translate -from zope.interface import implements, implementer, Interface -from zope.component import adapts, adapter, getMultiAdapter, getAdapter, getAdapters -from zope.annotation.interfaces import IAnnotations - -from Products.CMFCore.utils import getToolByName -from Products.CMFPlone.Portal import PloneSite - -from pcommerce.core import events -from pcommerce.core.config import INITIALIZED, SENT, CANCELED, FAILED, PROCESSED -from pcommerce.core.currency import CurrencyAware -from pcommerce.core.cart import Cart -from pcommerce.core import interfaces -from pcommerce.core import PCommerceMessageFactory as _ - -ANNOTATIONS_KEY_ORDERS = 'pcommerce.core.orders' -ORDER_SESSION_KEY = 'pcommerce.orderid' -CART_SESSION_KEY = 'pcommerce.core.cart' - -class Order(Persistent): - """""" - implements(interfaces.IOrder) - - state = INITIALIZED - processed_steps = () - orderid = '' - userid = '' - products = None - date = None - price = 0.0 - currency = '' - zone = None - address = None - shipmentids = None - shipmentdata = None - paymentid = None - paymentdata = None - pretaxcharges = None - posttaxcharges = None - _taxincl = None - - def __init__(self, - orderid, - userid, - price=0.0, - currency='', - date=None, - zone=None, - address=None, - products=[], - shipmentids={}, - shipmentdata={}, - paymentid=None, - paymentdata=None, - pretaxcharges=(), - posttaxcharges=(), - taxincl=None): - """""" - self.orderid = orderid - self.userid = userid - self.price = price - self.currency = currency - self.date = date - self.zone = zone - self.address = address - self.products = products - self.shipmentids = shipmentids - self.shipmentdata = shipmentdata - self.paymentid = paymentid - self.paymentdata = paymentdata - self.pretaxcharges = pretaxcharges - self.posttaxcharges = posttaxcharges - self._taxincl = taxincl - - @property - def tax(self): - if self.zone is None: - return 0 - return self.zone[1][0] - - @property - def taxname(self): - if self.zone is None: - return None - return self.zone[1][1] - - @property - def taxincl(self): - if self._taxincl is None: - return 0 - return self._taxincl[0] - - @property - def taxinclname(self): - if self._taxincl is None: - return None - return self._taxincl[1] - - @property - def zonename(self): - if self.zone is None: - return None - return self.zone[0] - - @property - def pretaxcharge(self): - charge = 0 - for data in self.shipmentdata.values(): - charge += getattr(data, 'pretaxcharge', 0) - charge += getattr(self.paymentdata, 'pretaxcharge', 0) - for data in self.pretaxcharges: - charge += getattr(data, 'price', 0) - return charge - - @property - def posttaxcharge(self): - charge = 0 - for data in self.shipmentdata.values(): - charge += getattr(data, 'posttaxcharge', 0) - charge += getattr(self.paymentdata, 'posttaxcharge', 0) - for data in self.posttaxcharges: - charge += getattr(data, 'price', 0) - return charge - - @property - def subtotal(self): - return self.price + self.pretaxcharge - - @property - def pricetax(self): - return self.subtotal * self.tax / 100 - - @property - def pricetaxincl(self): - return self.subtotal / 100 * self.taxincl - - @property - def total(self): - return self.subtotal + self.pricetax - - @property - def totalincl(self): - return self.total + self.posttaxcharge - -class OrderRegistry(Cart): - """""" - implements(interfaces.IOrderRegistry) - adapts(Interface) - - def __init__(self, context): - self.context = context - self.portal = context - if not isinstance(context, PloneSite): - self.portal = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').portal() - - @property - def _items(self): - annotations = IAnnotations(self.portal) - items = annotations.get(ANNOTATIONS_KEY_ORDERS, OOBTree()) - # BBB - if not isinstance(items, OOBTree): - btree_items = OOBTree() - for key, value in items: - btree_items[key] = value - items = btree_items - return items - - def getOrders(self): - """ returns a list of orders - """ - return self._items - - def getOrder(self, orderid): - """ returns a order by its id - """ - if not self.has_key(orderid): - return None - return self[orderid] - - def create(self, order): - """ generates an order from the cart - """ - member = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').member() - cart = interfaces.IShoppingCart(self.context) - if not len(cart): - return - order.userid = member.getId() - order.date = time() - order.currency = CurrencyAware(0).getCurrencySymbol() - products = cart.getProducts() - order_products = PersistentList() - price = 0 - for product in products: - price += product['price_raw'] * product['amount'] - order_products.append((product['uid'], - product['no'], - product['title'], - product['amount'], - product['price_raw'], - [(variation['uid'], variation['type'], variation['name']) for variation in product['variations']])) - if order_products != order.products: - order.processed_steps = () - order.products = order_products - order.price = price - - order._taxincl = interfaces.ITaxes(self.context).taxincl - - pretaxcharges = [] - providers = getAdapters((self.context,), interfaces.IPreTaxCharge) - for name, provider in providers: - pretaxcharges.append(provider.process(order)) - order.pretaxcharges = tuple(pretaxcharges) - - posttaxcharges = [] - providers = getAdapters((self.context,), interfaces.IPostTaxCharge) - for name, provider in providers: - posttaxcharges.append(provider.process(order)) - order.posttaxcharges = tuple(posttaxcharges) - - self[order.orderid] = order - - def recover(self, orderid): - """ recover an order from the registry - """ - if not self.has_key(orderid): - return - order = self[orderid] - cart = interfaces.IShoppingCart(self.context) - cart.clear() - for uid, title, price_raw, amount, variations in order.products: - if variations: - cart.addVariation([uid for uid, type, name in variations], amount) - else: - cart.add(uid, amount) - - notify(events.OrderRecoveredEvent(self, order)) - - def send(self, orderid, lang=None): - """ sends an order - """ - request = self.context.REQUEST - if not self.has_key(orderid): - return - order = self[orderid] - if order.state >= SENT: - if order.orderid == request.SESSION.get(ORDER_SESSION_KEY, 0): - request.SESSION.set(ORDER_SESSION_KEY, None) - return - portal_state = getMultiAdapter((self.context, request), name=u'plone_portal_state') - address = order.address - shipments = [] - shipments_customer = [] - product_shipment = {} - id_shipment = {} - i = 1 - for shipmentid, products in order.shipmentids.items(): - shipment = getAdapter(self.context, name=shipmentid, interface=interfaces.IShipmentMethod) - info = translate(shipment.mailInfo(order), context=request, target_language=lang) - if len(order.shipmentids) > 1: - info = '(%s) %s' % (i, info) - shipments.append(info) - - info_customer = translate(shipment.mailInfo(order, lang, customer=True), context=request, target_language=lang) - if len(order.shipmentids) > 1: - info = '(%s) %s' % (i, info_customer) - shipments_customer.append(info_customer) - - for product in products: - product_shipment[product] = i - id_shipment[shipmentid] = {'title': shipment.title, - 'number': i} - i += 1 - - payment = getAdapter(self.context, name=order.paymentid, interface=interfaces.IPaymentMethod) - alignment = Alignment() - - cart = [] - cart.append([translate(_('Product'), context=request, target_language=lang), - translate(_('Amount'), context=request, target_language=lang), - translate(_('Price'), context=request, target_language=lang), - translate(_('Price total'), context=request, target_language=lang)]) - cart.extend(['-', '']) - - for product in order.products: - cart.append([len(order.shipmentids) > 1 and '%s (%s)' % (product[1], product_shipment[product[0]]) or product[1], - str(product[3]), - ">"+CurrencyAware(product[4]).valueToString(order.currency), - ">"+CurrencyAware(product[4] * product[3]).valueToString(order.currency)]) - cart.append(product[2].decode('utf-8')) - for variation in product[5]: - cart.append("\t%s: %s" % (variation[1].decode('utf-8'), variation[2].decode('utf-8'))) - cart.append("") - - cart.append('-') - cart.append(['%s:' % translate(_('Total'), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.price).valueToString(order.currency)]) - cart.extend(['-', '']) - - if order.pretaxcharge: - if order.paymentdata.pretaxcharge: - cart.append(['%s:' % translate(payment.title, context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.paymentdata.pretaxcharge).valueToString(order.currency)]) - for shipmentid, data in order.shipmentdata.items(): - if data.pretaxcharge: - cart.append(['%s:' % (len(order.shipmentids) > 1 and '%s (%s)' % (translate(id_shipment[shipmentid]['title'], context=request, target_language=lang), id_shipment[shipmentid]['number']) or translate(id_shipment[shipmentid]['title'], context=request, target_language=lang)), '', '', - ">"+CurrencyAware(data.pretaxcharge).valueToString(order.currency)]) - for charge in order.pretaxcharges: - if charge.price: - cart.append(['%s:' % translate(charge.title, context=request, target_language=lang), '', '', - ">"+CurrencyAware(charge.price).valueToString(order.currency)]) - cart.append('-') - cart.append(['%s:' % translate(_('Total incl. charges'), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.subtotal).valueToString(order.currency)]) - cart.extend(['-', '']) - - if order.tax: - cart.append([order.taxname, '', '', - '%(pricetax)s (%(tax)s %% - %(zone)s)' % dict(tax=order.tax, - pricetax=">"+CurrencyAware(order.pricetax).valueToString(order.currency), - zone=address.zone)]) - cart.append('-') - cart.append(['%s:' % translate(_('Total incl. ${taxname}', mapping=dict(taxname=order.taxname)), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.total).valueToString(order.currency)]) - cart.extend(['-', '']) - - if order.taxincl and order.posttaxcharge is None: - cart.append([order.taxname, '', '', - '%(pricetax)s (%(tax)s %% - %(zone)s)' % dict(tax=order.tax, - pricetax=">"+CurrencyAware(order.pricetax).valueToString(order.currency), - zone=address.zone)]) - cart.append('-') - cart.append(['%s:' % translate(_('Total incl. ${tax}% ${taxname}', mapping=dict(tax=order.taxincl, taxname=order.taxinclname)), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) - cart.extend(['-', '']) - - - if order.posttaxcharge: - if order.paymentdata.posttaxcharge: - cart.append(['%s:' % translate(payment.title, context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.paymentdata.posttaxcharge).valueToString(order.currency)]) - for shipmentid, data in order.shipmentdata.items(): - if data.posttaxcharge: - cart.append(['%s:' % (len(order.shipmentids) > 1 and '%s (%s)' % (translate(id_shipment[shipmentid]['title'], context=request, target_language=lang), id_shipment[shipmentid]['number']) or translate(id_shipment[shipmentid]['title'], context=request, target_language=lang)), '', '', - ">"+CurrencyAware(data.posttaxcharge).valueToString(order.currency)]) - for charge in order.posttaxcharges: - if charge.price: - cart.append(['%s:' % translate(charge.title, context=request, target_language=lang), '', '', - ">"+CurrencyAware(charge.price).valueToString(order.currency)]) - cart.append('-') - if order.tax: - cart.append(['%s:' % translate(_('Total incl. charges and ${taxname}', mapping=dict(taxname=order.taxname)), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) - elif order.taxincl: - cart.append(['%s:' % translate(_('Total incl. charges and ${tax}% ${taxname}', mapping=dict(tax=order.taxincl, taxname=order.taxinclname)), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) - else: - cart.append(['%s:' % translate(_('Total incl. charges'), context=request, target_language=lang), '', '', - ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) - cart.extend(['-', '']) - - alignment.extend(cart) - - # do alignment - cart = alignment.alignItems(cart) - - email_from = getToolByName(self.context, 'portal_properties').pcommerce_properties.getProperty('email_address', '') - if not email_from: - email_from = portal_state.portal().getProperty('email_from_address', '') - email_from_name = portal_state.portal().getProperty('email_from_name', '') - mapping = {'orderid': order.orderid, - 'shipments': '\n\n'.join(shipments), - 'payment': translate(payment.mailInfo(order, lang), context=request, target_language=lang), - 'cart': '\n'.join(cart), - 'currency': order.currency, - 'address': address.mailInfo(request, lang), - 'name': address.firstname +' '+ address.lastname, - 'from_name': email_from_name, - 'from_email': email_from} - - mailhost = getToolByName(self.context, 'MailHost') - mailhost.secureSend(translate(self.getMessage(mapping), context=request, target_language=lang), - mto=email_from, - mfrom='%s <%s>' % (address.firstname +' '+ address.lastname, address.email), - subject=translate(_('email_order_title', default='New order [${orderid}]', mapping={'orderid': order.orderid}), context=request, target_language=lang), - charset='utf-8') - - mapping.update({'shipments': '\n\n'.join(shipments_customer), - 'payment': translate(payment.mailInfo(order, lang, customer=True), context=request, target_language=lang), - 'address': address.mailInfo(request, lang, True)}) - mailhost.secureSend(translate(self.getMessageCustomer(mapping), context=request, target_language=lang), - mto='%s <%s>' % (address.firstname +' '+ address.lastname, address.email), - mfrom='%s <%s>' % (email_from_name, email_from), - subject=translate(_('email_customer_title', default='Confirmation e-mail'), context=request, target_language=lang), - charset='utf-8') - - notify(events.OrderSentEvent(self, order)) - - order.state = SENT - if order.orderid == request.SESSION.get(ORDER_SESSION_KEY, 0): - request.SESSION.set(ORDER_SESSION_KEY, None) - - def process(self, orderid): - """ process an order - """ - if not self.has_key(orderid): - return - order = self[orderid] - - notify(events.OrderProcessedEvent(self, order)) - - order.state = PROCESSED - if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): - self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) - - # clear the shopping cart - self.context.REQUEST.SESSION.set(CART_SESSION_KEY, None) - - def cancel(self, orderid): - """ cancel an order - """ - if not self.has_key(orderid): - return - order = self[orderid] - - notify(events.OrderCanceledEvent(self, order)) - - order.state = CANCELED - if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): - self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) - - def fail(self, orderid): - """ fail an order - """ - if not self.has_key(orderid): - return - order = self[orderid] - - notify(events.OrderFailedEvent(self, order)) - - order.state = FAILED - if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): - self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) - - def getMessage(self, mapping): - return _('email_order_body', default=\ -"""New order by ${name} - -Orderid: ${orderid} - -${cart} -Currency: ${currency} - - -Address: -${address} - -Payment: -${payment} - -Shipment: -${shipments} - -""", mapping=mapping) - - def getMessageCustomer(self, mapping): - return _('email_customer_body', default=\ -"""Dear ${name} - -Your order has been successfully registered. Please find a complete -overview of your order below. - -Order ID: ${orderid} - -${cart} -Currency: ${currency} - - -Address: -${address} - -Payment: -${payment} - -Shipment: -${shipments} - - -If you have any questions concerning your purchase do not hesitate -to contact us at ${from_email}. - -Best regards - -${from_name}""", mapping=mapping) - - def _save(self): - annotations = IAnnotations(self.portal) - annotations[ANNOTATIONS_KEY_ORDERS] = self._items - -class Alignment(object): - - separate = 4 - rows = [] - - def align(self, item): - if not isinstance(item, list): - if item.startswith('-'): - return '-' * len(self) - return item - aligned = [] - for i in range(0, len(item)): - if item[i].startswith('>'): - item[i] = item[i][1:] - aligned.append((' ' * (self.max(i) - len(item[i]))) + item[i]) - else: - aligned.append(item[i] + (' ' * (self.max(i) - len(item[i])))) - return (' ' * self.separate).join(aligned) - - def alignItems(self, items): - return [self.align(item) for item in items] - - def append(self, item): - self.rows.append(item) - - def extend(self, items): - self.rows.extend(items) - - def max(self, i): - return max([len(row[i]) for row in self.rows if isinstance(row, list) and len(row) > i]) - - def __len__(self): - l = 0 - for i in range(0, max([len(row) for row in self.rows if isinstance(row, list)])): - l += self.max(i) - l += i * self.separate - return l - -@adapter(Interface) -@implementer(interfaces.IOrder) -def get_order(context): - orderid = context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0) - order = None - orders = interfaces.IOrderRegistry(context) - if orderid and orders.has_key(orderid): - order = orders[orderid] - if order.state is INITIALIZED: - notify(events.OrderAboutToBeRecreatedEvent(orders, order)) - orders.create(order) - notify(events.OrderRecreatedEvent(orders, order)) - else: - order = None - - if not order: - orderid = int(time()*100) - context.REQUEST.SESSION.set(ORDER_SESSION_KEY, orderid) - order = Order(orderid, None) - orders.create(order) - - notify(events.OrderCreatedEvent(orders, order)) - - return order diff --git a/pcommerce/core/permissions.zcml b/pcommerce/core/permissions.zcml deleted file mode 100644 index a6615a1..0000000 --- a/pcommerce/core/permissions.zcml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/pcommerce/core/plone3.py b/pcommerce/core/plone3.py deleted file mode 100644 index dc115a5..0000000 --- a/pcommerce/core/plone3.py +++ /dev/null @@ -1,2 +0,0 @@ -from Products.PlacelessTranslationService.utility import PTSTranslationDomain -pcommercedomain = PTSTranslationDomain('pcommerce') \ No newline at end of file diff --git a/pcommerce/core/processor.py b/pcommerce/core/processor.py deleted file mode 100644 index c42537a..0000000 --- a/pcommerce/core/processor.py +++ /dev/null @@ -1,35 +0,0 @@ -from zope.interface import implements, Interface -from zope.component import adapts, getAdapter -from zope.event import notify - -from pcommerce.core import interfaces -from pcommerce.core.config import FAILED, PROCESSED, SENT -from pcommerce.core.events import OrderProcessingSuccessfulEvent, OrderProcessingFailedEvent - -class PaymentProcessor(object): - """""" - implements(interfaces.IPaymentProcessor) - adapts(Interface) - - def __init__(self, context): - self.context = context - - def processOrder(self, orderid, paymentid, lang=None): - orderid = int(orderid) - registry = interfaces.IOrderRegistry(self.context) - order = registry.getOrder(orderid) - if not order or not order.paymentid == paymentid: - return 'no matching order found' - if order.state is not PROCESSED and order.state is not FAILED: - method = getAdapter(self.context, name=paymentid, interface=interfaces.IPaymentMethod) - if method.verifyPayment(order): - if order.state < SENT: - registry.send(orderid, lang=None) - registry.process(orderid) - notify(OrderProcessingSuccessfulEvent(registry, order)) - return 'payment successfully processed' - else: - registry.fail(orderid) - notify(OrderProcessingFailedEvent(registry, order)) - return 'processing payment failed' - return 'payment already processed' diff --git a/pcommerce/core/profiles/default/actions.xml b/pcommerce/core/profiles/default/actions.xml deleted file mode 100644 index 807a492..0000000 --- a/pcommerce/core/profiles/default/actions.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Manage orders - List of all orders and their statuses - string:${globals_view/navigationRootUrl}/@@manage-orders - - python:member is not None - - - - True - - - diff --git a/pcommerce/core/profiles/default/catalog.xml b/pcommerce/core/profiles/default/catalog.xml deleted file mode 100644 index cf847a2..0000000 --- a/pcommerce/core/profiles/default/catalog.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/pcommerce/core/profiles/default/controlpanel.xml b/pcommerce/core/profiles/default/controlpanel.xml deleted file mode 100644 index bd743c0..0000000 --- a/pcommerce/core/profiles/default/controlpanel.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Manage portal - - - diff --git a/pcommerce/core/profiles/default/cssregistry.xml b/pcommerce/core/profiles/default/cssregistry.xml deleted file mode 100644 index 3804ac7..0000000 --- a/pcommerce/core/profiles/default/cssregistry.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/pcommerce/core/profiles/default/factorytool.xml b/pcommerce/core/profiles/default/factorytool.xml deleted file mode 100644 index 618b266..0000000 --- a/pcommerce/core/profiles/default/factorytool.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/pcommerce/core/profiles/default/jsregistry.xml b/pcommerce/core/profiles/default/jsregistry.xml deleted file mode 100644 index 2db2b1a..0000000 --- a/pcommerce/core/profiles/default/jsregistry.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/pcommerce/core/profiles/default/metadata.xml b/pcommerce/core/profiles/default/metadata.xml deleted file mode 100644 index 9a5dd3c..0000000 --- a/pcommerce/core/profiles/default/metadata.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - 10 - - profile-Products.SingleKeywordWidget:default - - diff --git a/pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt b/pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt deleted file mode 100644 index e69de29..0000000 diff --git a/pcommerce/core/profiles/default/portlets.xml b/pcommerce/core/profiles/default/portlets.xml deleted file mode 100644 index 1417286..0000000 --- a/pcommerce/core/profiles/default/portlets.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/propertiestool.xml b/pcommerce/core/profiles/default/propertiestool.xml deleted file mode 100644 index 52a4e64..0000000 --- a/pcommerce/core/profiles/default/propertiestool.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - PCommerce order - - - - 3 - 0 - 3 - 6 - 0 - 2 - 2 - 0 - 0 - 5 - - diff --git a/pcommerce/core/profiles/default/rolemap.xml b/pcommerce/core/profiles/default/rolemap.xml deleted file mode 100644 index f328596..0000000 --- a/pcommerce/core/profiles/default/rolemap.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/skins.xml b/pcommerce/core/profiles/default/skins.xml deleted file mode 100644 index a76d3e3..0000000 --- a/pcommerce/core/profiles/default/skins.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/pcommerce/core/profiles/default/types.xml b/pcommerce/core/profiles/default/types.xml deleted file mode 100644 index b5a6987..0000000 --- a/pcommerce/core/profiles/default/types.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/types/Folder.xml b/pcommerce/core/profiles/default/types/Folder.xml deleted file mode 100644 index 484795b..0000000 --- a/pcommerce/core/profiles/default/types/Folder.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/types/Price.xml b/pcommerce/core/profiles/default/types/Price.xml deleted file mode 100644 index c578c7a..0000000 --- a/pcommerce/core/profiles/default/types/Price.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - Price - A price - ++resource++price_icon.gif - Price - pcommerce.core - addPrice - view - False - True - - False - - - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/types/Product.xml b/pcommerce/core/profiles/default/types/Product.xml deleted file mode 100644 index 7c38820..0000000 --- a/pcommerce/core/profiles/default/types/Product.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - Product - A product - ++resource++product_icon.gif - Product - pcommerce.core - addProduct - view - True - True - view - - - - - - False - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/types/Variation.xml b/pcommerce/core/profiles/default/types/Variation.xml deleted file mode 100644 index 63cd229..0000000 --- a/pcommerce/core/profiles/default/types/Variation.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - Variation - A variation of a product - ++resource++variation_icon.gif - Variation - pcommerce.core - addVariation - view - False - True - view - - - - - False - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pcommerce/core/profiles/default/viewlets.xml b/pcommerce/core/profiles/default/viewlets.xml deleted file mode 100644 index 2ab9d3e..0000000 --- a/pcommerce/core/profiles/default/viewlets.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/pcommerce/core/registry.py b/pcommerce/core/registry.py deleted file mode 100644 index cf383d2..0000000 --- a/pcommerce/core/registry.py +++ /dev/null @@ -1,28 +0,0 @@ -from zope.interface import implements, Interface -from zope.component import adapts, getAdapters - -from pcommerce.core import interfaces - -class Shipment(object): - """shipment-registry""" - implements(interfaces.IShipmentRegistry) - adapts(Interface) - - def __init__(self, context): - self.context = context - - def getShipmentMethods(self): - """get all registered shipment-methods""" - return dict([(name, adapter) for name, adapter in getAdapters((self.context,), interfaces.IShipmentMethod)]) - -class Payment(object): - """payment-registry""" - implements(interfaces.IPaymentRegistry) - adapts(Interface) - - def __init__(self, context): - self.context = context - - def getPaymentMethods(self): - """get all registered payment-methods""" - return dict([(name, adapter) for name, adapter in getAdapters((self.context,), interfaces.IPaymentMethod)]) diff --git a/pcommerce/core/required.py b/pcommerce/core/required.py deleted file mode 100644 index 27a90d6..0000000 --- a/pcommerce/core/required.py +++ /dev/null @@ -1,9 +0,0 @@ -from zope.interface import implementer, Interface -from zope.component import adapter - -from pcommerce.core.interfaces import IRequiredComponents - -@adapter(Interface) -@implementer(IRequiredComponents) -def components(context): - return ('address', 'shipments', 'shipment', 'payments', 'payment', 'overview', 'gtc',) diff --git a/pcommerce/core/setuphandlers.py b/pcommerce/core/setuphandlers.py deleted file mode 100644 index 62cb69a..0000000 --- a/pcommerce/core/setuphandlers.py +++ /dev/null @@ -1,19 +0,0 @@ -from pcommerce.core.interfaces import IOrderRegistry - -def migrate05a105a2(context): - - if context.readDataFile('pcommerce.core_migrate05a105a2.txt') is None: - return - - portal = context.getSite() - - registry = IOrderRegistry(portal) - for order in registry.getOrders().itervalues(): - if hasattr(order.paymentdata, 'shipmentid'): - order.paymentdata.id = order.paymentdata.shipmentid - delattr(order.paymentdata, 'shipmentid') - for data in order.shipmentdata.values(): - if hasattr(data, 'shipmentid'): - data.id = data.shipmentid - delattr(data, 'shipmentid') - \ No newline at end of file diff --git a/pcommerce/core/skins/pcommerce/pcommerce.css.dtml b/pcommerce/core/skins/pcommerce/pcommerce.css.dtml deleted file mode 100644 index e7fef27..0000000 --- a/pcommerce/core/skins/pcommerce/pcommerce.css.dtml +++ /dev/null @@ -1,530 +0,0 @@ -/* (do not remove this :) */ -/* (not this either :) */ - -/* shopping cart portlet */ - -.portletShoppingCart .portletItem { - font-size:90%; -} - -.portletShoppingCart .portletItem dt { - clear:left; - float:left; - width:60%; - font-weight:normal; - background-color:transparent; - padding-top:0; - padding-bottom:0; - line-height:2em; -} - -.portletShoppingCart .portletItem dd { - padding:0; - margin:0; - font-weight:bold; - line-height:2em; -} - -.portletShoppingCart .portletFooter { - clear:both; -} - -.portletShoppingCart .portletFooter a { - font-weight:bold; -} - - -/* shopping cart */ - -#cart .formControls { - text-align:right; -} - -#cart table { - position:relative; - border:none; - padding:0; - margin:0 0 1em 0; - border-collapse: collapse; -} - -#cart table th, -#cart table td { - vertical-align:baseline; - margin:0; - padding:0.5em 1em; - white-space:nowrap; - border-width:0 0 &dtml-borderWidth; 0; - border-style:&dtml-borderStyle;; - border-color:&dtml-globalBorderColor;; -} - -#cart table .info { - text-align:left; - width:100%; - white-space:normal; -} - -#cart table .amount { - text-align:center; -} - -#cart table .price { - text-align:right; -} - -#cart table tfoot td, -#cart table tfoot th { - background-color:&dtml-globalBackgroundColor;; -} - -#cart table tr.discreet th, -#cart table tr.discreet td { - background-color: &dtml-evenRowBackgroundColor;; - padding-top:0.2em; - padding-bottom:0.2em; -} - -#cart .formControls input.standalone { - background-image:none; - padding:1px; -} - -#cart .formControls input.context { - padding:1px 8px 1px 1px; - background-image:url("arrowRight.gif"); - background-position:right center; - background-repeat:no-repeat; -} - - -/* checkout */ - -#checkout .component { - margin:1em 0; - padding:1em; - border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; -} - -#checkout .component h2 { - margin:0 0 1em 0; - font-size:1.2em; -} - -#checkout .formControls { - clear:both; - text-align:center; - height:2em; - position:relative; -} - -#checkout .formControls input { - background-image:none; - padding:1px; -} - -#checkout .formControls .next { - display:block; - position:absolute; - right:0; - padding-right:8px; - background-image:url("arrowRight.gif"); - background-position:right center; - background-repeat:no-repeat; -} - -#checkout .formControls .previous { - position:absolute; - left:0; - padding-left:8px; - background-image:url("arrowLeft.gif"); - background-position:left center; - background-repeat:no-repeat; -} - -#checkout .formControls .checkout { - padding-right:12px; - background-image:url("arrowRightmost.gif"); - background-repeat:no-repeat; -} - -#checkout .field { - clear:both; - position:relative; - margin-right:0; -} - -#checkout .component input, -#checkout .component textarea { - width:95%; -} - -#checkout .component input.noborder { - width:auto; -} - -#checkout .field.error { - width:auto; -} - -#checkout .address .field label { - float:left; - width:120px; - margin-bottom:0.5em; -} - -#checkout .address .field .widget { - margin:0 10px 0 120px; -} - -* html #checkout .address .field .widget, -*+html #checkout .address .field .widget { - float:left; - margin:0; -} - -#checkout .address .field .fieldRequired { - position:absolute; - right:0; - width:1px; - overflow:hidden; -} - -#checkout .address .field .zip_city_wrap { - width:95%; - left:0; -} - -#checkout .address .field .zip { - display:inline; - width:10%; - margin:0; -} - -#checkout .address .field .city { - display:inline; - width:87%; - margin: 0 -2px 0 0; - float: right; -} - -#checkout .steps { - position: relative; - text-align: center; - margin-top:1em; -} - -#checkout .steps .step { - display:inline; - padding: 0.5em; - text-decoration: none; - border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; -} - -* html #checkout .steps .step, -*+html #checkout .steps .step { - margin:0 0.2em; -} - -#checkout .steps .step.select { - background-color:&dtml-globalBackgroundColor;; -} - -#checkout .description { - margin:0; -} - -#checkout ul.products { - margin-top:0; - margin-bottom:1em; - font-size:0.9em; -} - -#checkout #shipment .shipment { - margin:0 0 2em 0; -} - -#checkout ul.selection li { - padding:0; - margin:0; - display:block; -} - -#checkout ul.selection label { - display:block; - padding:0.5em; - font-weight:normal; - line-height:1.2em; -} - -#checkout ul.selection label:hover { - cursor:pointer; - background-color:&dtml-globalBackgroundColor;; -} - -#checkout ul.selection label input { - float:left; - display:block; - margin:0 1em 0 0; -} - -#checkout ul.selection label img, -#checkout .logo { - display:block; - float:right; - margin:0 0 0 1em; - border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; -} - -#checkout .logo { - margin-bottom:1em; -} - -#checkout ul.selection label strong, -#checkout ul.selection label span { - display:block; - margin-left:3em; -} - -#checkout .overview { - position:relative; - width:100%; -} - -#checkout .overview .box { - float:left; - width:27%; - border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; - margin:0 3% 0 0; - padding:2%; - overflow:hidden; -} - -#checkout .overview .box h3 { - font-size:1.1em; - font-weight:bold; - margin:0; - border:none; -} - -#checkout .overview .box h4 { - font-size:1em; - font-weight:bold; -} - -#checkout .overview .box .shipmentinfo { - margin-bottom:1em; -} - -#checkout .overview .shipment { - margin-right:0; -} - -#checkout .overview .payment { - float:right; - margin-right:0; -} - -#checkout #cart { - margin:1em 0; -} - - -/* product view */ - -.productInfo a { - display:block; - margin:0 0 0 40px; -} - -.productInfo .no { - display:block; - font-size:90%; - margin:0 0 0.5em 40px; -} - -.productInfo .productImage { - float:left; - margin:0; -} - -.productInfo dl { - clear:both; - font-size:90%; - margin:0 0 0 40px; - padding:0; - line-height:normal; -} - -.productInfo dl dt { - display:block; - float:left; - clear:left; - width:70px; - padding:0; - margin:0; - line-height:normal; -} - -.productInfo dl dd { - display:block; - padding:0; - margin:0 0 0 75px; - line-height:normal; -} - -.addLink { - display:block; - float:right; - font-size:90%; - text-decoration:none; - margin:1.4em 0.5em 0 0; - padding:0 0.5em; - background-color:&dtml-backgroundColor;; -} - -.portletInfoBox { - float:right; - margin:0 0 1em 1em; -} - -* html .portletInfoBox { - width:1%; -} - -.portletInfoBox .portletItem { - border-top:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; -} - -.portletInfoBox .portletItem img { - display:block; -} - -.priceInfo { - font-size:90%; -} - -.buyViewlet { - clear:both; - background-color:&dtml-globalBackgroundColor;; - border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; - margin:1em 0 2em 0; -} - -.buyViewlet form { - clear:both; - padding:0.8em 1em; -} - -.buyViewlet input, -.buyViewlet select, -.buyViewlet label { - margin:0 0.5em 0.5em 0; - display:block; - float:left; -} - -.buyViewlet .context { - background-color:&dtml-backgroundColor;; - background-image:none; - padding-left:1px; -} - -.buyViewlet label { - clear:left; - font-size:90%; - color:&dtml-linkColor;; - line-height:1.4em; -} - -.productList { - position:relative; - clear:both; - margin:4em 0; -} - -.productList .list { - position:relative; - margin:0 0 1em 0; -} - -.new .list { - margin-right:0; -} - -.portletProduct { - width:30.5%; - float:left; - margin-right:2%; -} - -.portletProduct.col3, -* html .portletProduct.col3 { - float:right; - margin-right:0; -} - -.new .portletProduct { - width:48%; - margin-right:0; -} - -.portletProduct.col1 { - clear:both; -} - -.new .portletProduct.col2 { - float:right; -} - -.portletProduct .portletItem { - border-top:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; -} - -.portletProduct .portletItem a, -.portletProduct .description { - border-bottom:none; - display:block; -} - -.portletProduct .portletItem a.image { - margin-bottom:0.5em; -} - -.portletProduct .priceInfo { - font-size:100%; -} - - -/* configlet */ - -#pcommerce_configlet table th { - text-align:left; -} - -.clearfix:after, -.component:after { - content: "."; - display: block; - clear: both; - visibility: hidden; - line-height: 0; - height: 0; -} - -.clearfix, -.component { - display: inline-block; -} - -html[xmlns] .clearfix, -html[xmlns] .component { - display: block; -} - -* html .clearfix, -* html .component { - height: 1%; -} - -/* */ \ No newline at end of file diff --git a/pcommerce/core/steps.py b/pcommerce/core/steps.py deleted file mode 100644 index f51c547..0000000 --- a/pcommerce/core/steps.py +++ /dev/null @@ -1,16 +0,0 @@ -from zope.interface import implementer, Interface -from zope.component import adapter - -from pcommerce.core.interfaces import ISteps -from pcommerce.core import PCommerceMessageFactory as _ - -@adapter(Interface) -@implementer(ISteps) -def steps(context): - return ({'name':_('Address'), 'components':('address',)}, - {'name':_('Shipment'), 'components':('shipments',)}, - {'name':_('Shipment'), 'components':('shipment',)}, - {'name':_('Payment'), 'components':('payments',)}, - {'name':_('Payment'), 'components':('payment',)}, - {'name':_('Overview'), 'components':('overview', 'gtc',)}, - {'name':_('Confirmation'), 'components':('confirmation',)}) \ No newline at end of file diff --git a/pcommerce/core/vocabulary.py b/pcommerce/core/vocabulary.py deleted file mode 100644 index d9ae1c1..0000000 --- a/pcommerce/core/vocabulary.py +++ /dev/null @@ -1,27 +0,0 @@ -from zope.interface import implementer, implements -from zope.component import adapter, adapts -from zope.schema.interfaces import IVocabularyFactory -from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm - -from Products.Archetypes.interfaces import IFieldDefaultProvider - -from pcommerce.core.interfaces import IShipmentRegistry, IProduct - -@implementer(IVocabularyFactory) -def shipments(context): - shipments = [] - registry = IShipmentRegistry(context) - r_shipments = registry.getShipmentMethods() - for name, shipment in r_shipments.items(): - shipments.append(SimpleTerm(name, name, shipment.title)) - return SimpleVocabulary(shipments) - -class ShipmentsDefault(object): - implements(IFieldDefaultProvider) - adapts(IProduct) - def __init__(self, context): - self.context = context - def __call__(self): - vocabulary = shipments(self.context) - for term in vocabulary: - yield term.value diff --git a/setup.py b/setup.py index 968bdcc..e692c5e 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,8 @@ author_email='dev@raptus.com', url='https://github.com/Raptus/pcommerce.core', license='GPL', - packages=find_packages(exclude=['ez_setup']), + packages=find_packages('src'), + package_dir={'': 'src'}, namespace_packages=['pcommerce'], include_package_data=True, zip_safe=False, From af508216373dd683971bbf706a35d80a41c42490 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 12:44:46 +0100 Subject: [PATCH 02/27] egg moved into src --- src/pcommerce/__init__.py | 6 + src/pcommerce/core/__init__.py | 26 + src/pcommerce/core/adapters.py | 150 ++++ src/pcommerce/core/address.py | 108 +++ src/pcommerce/core/browser/.configlet.pt.swp | Bin 0 -> 24576 bytes src/pcommerce/core/browser/__init__.py | 0 src/pcommerce/core/browser/address.pt | 348 ++++++++ src/pcommerce/core/browser/cart.pt | 131 +++ src/pcommerce/core/browser/cart.py | 49 ++ src/pcommerce/core/browser/checkout.pt | 72 ++ src/pcommerce/core/browser/checkout.py | 376 +++++++++ .../core/browser/components/__init__.py | 0 .../core/browser/components/address.pt | 17 + .../core/browser/components/address.py | 26 + src/pcommerce/core/browser/components/base.py | 273 +++++++ .../core/browser/components/configure.zcml | 61 ++ .../core/browser/components/confirmation.pt | 63 ++ .../core/browser/components/confirmation.py | 16 + src/pcommerce/core/browser/components/gtc.pt | 28 + src/pcommerce/core/browser/components/gtc.py | 27 + .../core/browser/components/overview.pt | 55 ++ .../core/browser/components/overview.py | 16 + .../core/browser/components/payment.pt | 17 + .../core/browser/components/payment.py | 27 + .../core/browser/components/payments.pt | 38 + .../core/browser/components/payments.py | 29 + .../core/browser/components/shipment.pt | 26 + .../core/browser/components/shipment.py | 50 ++ .../core/browser/components/shipments.pt | 89 ++ .../core/browser/components/shipments.py | 63 ++ src/pcommerce/core/browser/configlet.pt | 276 +++++++ src/pcommerce/core/browser/configlet.py | 92 +++ src/pcommerce/core/browser/configure.zcml | 190 +++++ src/pcommerce/core/browser/folder.pt | 51 ++ src/pcommerce/core/browser/folder.py | 92 +++ src/pcommerce/core/browser/getprice.js | 27 + src/pcommerce/core/browser/getprice.pt | 8 + src/pcommerce/core/browser/getprice.py | 40 + src/pcommerce/core/browser/images.pt | 132 +++ src/pcommerce/core/browser/images.py | 52 ++ .../core/browser/images/price_icon.gif | Bin 0 -> 595 bytes .../core/browser/images/product_icon.gif | Bin 0 -> 1048 bytes .../core/browser/images/variation_icon.gif | Bin 0 -> 1048 bytes .../core/browser/javascripts/as_customer.js | 17 + src/pcommerce/core/browser/macros.pt | 220 +++++ src/pcommerce/core/browser/manage_orders.pt | 59 ++ src/pcommerce/core/browser/order_details.pt | 53 ++ src/pcommerce/core/browser/orders.py | 258 ++++++ .../core/browser/portlets/__init__.py | 0 src/pcommerce/core/browser/portlets/cart.pt | 30 + src/pcommerce/core/browser/portlets/cart.py | 52 ++ .../core/browser/portlets/configure.zcml | 17 + src/pcommerce/core/browser/prices.pt | 149 ++++ src/pcommerce/core/browser/prices.py | 58 ++ src/pcommerce/core/browser/product.pt | 36 + src/pcommerce/core/browser/product.py | 155 ++++ src/pcommerce/core/browser/variation.pt | 46 ++ src/pcommerce/core/browser/variation.py | 8 + src/pcommerce/core/browser/variations.pt | 41 + src/pcommerce/core/browser/variations.py | 11 + .../core/browser/viewlets/__init__.py | 0 src/pcommerce/core/browser/viewlets/buy.pt | 22 + src/pcommerce/core/browser/viewlets/buy.py | 46 ++ .../core/browser/viewlets/configure.zcml | 64 ++ src/pcommerce/core/browser/viewlets/hot.pt | 10 + src/pcommerce/core/browser/viewlets/hot.py | 54 ++ src/pcommerce/core/browser/viewlets/info.pt | 19 + src/pcommerce/core/browser/viewlets/info.py | 47 ++ src/pcommerce/core/browser/viewlets/new.pt | 10 + src/pcommerce/core/browser/viewlets/new.py | 54 ++ .../core/browser/viewlets/processor.py | 52 ++ .../core/browser/viewlets/related.pt | 10 + .../core/browser/viewlets/related.py | 56 ++ .../core/browser/viewlets/variation.pt | 10 + .../core/browser/viewlets/variation.py | 53 ++ src/pcommerce/core/cart.py | 256 ++++++ src/pcommerce/core/charge.py | 17 + src/pcommerce/core/config.py | 46 ++ src/pcommerce/core/configure.zcml | 70 ++ src/pcommerce/core/content/__init__.py | 0 src/pcommerce/core/content/price.py | 42 + src/pcommerce/core/content/product.py | 136 +++ src/pcommerce/core/content/variation.py | 62 ++ src/pcommerce/core/currency.py | 74 ++ src/pcommerce/core/data.py | 23 + src/pcommerce/core/events.py | 39 + src/pcommerce/core/interfaces.py | 488 +++++++++++ .../core/locales/de/LC_MESSAGES/pcommerce.po | 770 +++++++++++++++++ .../core/locales/de/LC_MESSAGES/plone.po | 54 ++ .../core/locales/es/LC_MESSAGES/pcommerce.po | 771 ++++++++++++++++++ .../core/locales/es/LC_MESSAGES/plone.po | 56 ++ .../core/locales/fr/LC_MESSAGES/pcommerce.po | 760 +++++++++++++++++ .../core/locales/fr/LC_MESSAGES/plone.po | 55 ++ .../core/locales/nl/LC_MESSAGES/pcommerce.po | 754 +++++++++++++++++ .../core/locales/nl/LC_MESSAGES/plone.po | 52 ++ .../core/locales/no/LC_MESSAGES/pcommerce.po | 752 +++++++++++++++++ .../core/locales/no/LC_MESSAGES/plone.po | 56 ++ src/pcommerce/core/locales/pcommerce.pot | 690 ++++++++++++++++ src/pcommerce/core/locales/plone.pot | 51 ++ src/pcommerce/core/order.py | 569 +++++++++++++ src/pcommerce/core/permissions.zcml | 39 + src/pcommerce/core/plone3.py | 2 + src/pcommerce/core/processor.py | 35 + .../profiles/default/.propertiestool.xml.swp | Bin 0 -> 12288 bytes .../core/profiles/default/actions.xml | 18 + .../core/profiles/default/catalog.xml | 15 + .../core/profiles/default/controlpanel.xml | 19 + .../core/profiles/default/cssregistry.xml | 6 + .../core/profiles/default/factorytool.xml | 9 + .../core/profiles/default/jsregistry.xml | 10 + .../core/profiles/default/metadata.xml | 7 + .../pcommerce.core_migrate05a105a2.txt | 0 .../core/profiles/default/portlets.xml | 10 + .../core/profiles/default/propertiestool.xml | 20 + .../core/profiles/default/rolemap.xml | 35 + src/pcommerce/core/profiles/default/skins.xml | 8 + src/pcommerce/core/profiles/default/types.xml | 10 + .../core/profiles/default/types/Folder.xml | 9 + .../core/profiles/default/types/Price.xml | 27 + .../core/profiles/default/types/Product.xml | 44 + .../core/profiles/default/types/Variation.xml | 43 + .../core/profiles/default/viewlets.xml | 20 + src/pcommerce/core/registry.py | 28 + src/pcommerce/core/required.py | 9 + src/pcommerce/core/setuphandlers.py | 19 + .../core/skins/pcommerce/pcommerce.css.dtml | 530 ++++++++++++ src/pcommerce/core/steps.py | 16 + src/pcommerce/core/vocabulary.py | 27 + 128 files changed, 12522 insertions(+) create mode 100644 src/pcommerce/__init__.py create mode 100644 src/pcommerce/core/__init__.py create mode 100644 src/pcommerce/core/adapters.py create mode 100644 src/pcommerce/core/address.py create mode 100644 src/pcommerce/core/browser/.configlet.pt.swp create mode 100644 src/pcommerce/core/browser/__init__.py create mode 100644 src/pcommerce/core/browser/address.pt create mode 100644 src/pcommerce/core/browser/cart.pt create mode 100644 src/pcommerce/core/browser/cart.py create mode 100644 src/pcommerce/core/browser/checkout.pt create mode 100644 src/pcommerce/core/browser/checkout.py create mode 100644 src/pcommerce/core/browser/components/__init__.py create mode 100644 src/pcommerce/core/browser/components/address.pt create mode 100644 src/pcommerce/core/browser/components/address.py create mode 100644 src/pcommerce/core/browser/components/base.py create mode 100644 src/pcommerce/core/browser/components/configure.zcml create mode 100644 src/pcommerce/core/browser/components/confirmation.pt create mode 100644 src/pcommerce/core/browser/components/confirmation.py create mode 100644 src/pcommerce/core/browser/components/gtc.pt create mode 100644 src/pcommerce/core/browser/components/gtc.py create mode 100644 src/pcommerce/core/browser/components/overview.pt create mode 100644 src/pcommerce/core/browser/components/overview.py create mode 100644 src/pcommerce/core/browser/components/payment.pt create mode 100644 src/pcommerce/core/browser/components/payment.py create mode 100644 src/pcommerce/core/browser/components/payments.pt create mode 100644 src/pcommerce/core/browser/components/payments.py create mode 100644 src/pcommerce/core/browser/components/shipment.pt create mode 100644 src/pcommerce/core/browser/components/shipment.py create mode 100644 src/pcommerce/core/browser/components/shipments.pt create mode 100644 src/pcommerce/core/browser/components/shipments.py create mode 100644 src/pcommerce/core/browser/configlet.pt create mode 100644 src/pcommerce/core/browser/configlet.py create mode 100644 src/pcommerce/core/browser/configure.zcml create mode 100644 src/pcommerce/core/browser/folder.pt create mode 100644 src/pcommerce/core/browser/folder.py create mode 100644 src/pcommerce/core/browser/getprice.js create mode 100644 src/pcommerce/core/browser/getprice.pt create mode 100644 src/pcommerce/core/browser/getprice.py create mode 100644 src/pcommerce/core/browser/images.pt create mode 100644 src/pcommerce/core/browser/images.py create mode 100644 src/pcommerce/core/browser/images/price_icon.gif create mode 100644 src/pcommerce/core/browser/images/product_icon.gif create mode 100644 src/pcommerce/core/browser/images/variation_icon.gif create mode 100644 src/pcommerce/core/browser/javascripts/as_customer.js create mode 100644 src/pcommerce/core/browser/macros.pt create mode 100644 src/pcommerce/core/browser/manage_orders.pt create mode 100644 src/pcommerce/core/browser/order_details.pt create mode 100644 src/pcommerce/core/browser/orders.py create mode 100644 src/pcommerce/core/browser/portlets/__init__.py create mode 100644 src/pcommerce/core/browser/portlets/cart.pt create mode 100644 src/pcommerce/core/browser/portlets/cart.py create mode 100644 src/pcommerce/core/browser/portlets/configure.zcml create mode 100644 src/pcommerce/core/browser/prices.pt create mode 100644 src/pcommerce/core/browser/prices.py create mode 100644 src/pcommerce/core/browser/product.pt create mode 100644 src/pcommerce/core/browser/product.py create mode 100644 src/pcommerce/core/browser/variation.pt create mode 100644 src/pcommerce/core/browser/variation.py create mode 100644 src/pcommerce/core/browser/variations.pt create mode 100644 src/pcommerce/core/browser/variations.py create mode 100644 src/pcommerce/core/browser/viewlets/__init__.py create mode 100644 src/pcommerce/core/browser/viewlets/buy.pt create mode 100644 src/pcommerce/core/browser/viewlets/buy.py create mode 100644 src/pcommerce/core/browser/viewlets/configure.zcml create mode 100644 src/pcommerce/core/browser/viewlets/hot.pt create mode 100644 src/pcommerce/core/browser/viewlets/hot.py create mode 100644 src/pcommerce/core/browser/viewlets/info.pt create mode 100644 src/pcommerce/core/browser/viewlets/info.py create mode 100644 src/pcommerce/core/browser/viewlets/new.pt create mode 100644 src/pcommerce/core/browser/viewlets/new.py create mode 100644 src/pcommerce/core/browser/viewlets/processor.py create mode 100644 src/pcommerce/core/browser/viewlets/related.pt create mode 100644 src/pcommerce/core/browser/viewlets/related.py create mode 100644 src/pcommerce/core/browser/viewlets/variation.pt create mode 100644 src/pcommerce/core/browser/viewlets/variation.py create mode 100644 src/pcommerce/core/cart.py create mode 100644 src/pcommerce/core/charge.py create mode 100644 src/pcommerce/core/config.py create mode 100644 src/pcommerce/core/configure.zcml create mode 100644 src/pcommerce/core/content/__init__.py create mode 100644 src/pcommerce/core/content/price.py create mode 100644 src/pcommerce/core/content/product.py create mode 100644 src/pcommerce/core/content/variation.py create mode 100644 src/pcommerce/core/currency.py create mode 100644 src/pcommerce/core/data.py create mode 100644 src/pcommerce/core/events.py create mode 100644 src/pcommerce/core/interfaces.py create mode 100644 src/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po create mode 100644 src/pcommerce/core/locales/de/LC_MESSAGES/plone.po create mode 100644 src/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po create mode 100644 src/pcommerce/core/locales/es/LC_MESSAGES/plone.po create mode 100755 src/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po create mode 100755 src/pcommerce/core/locales/fr/LC_MESSAGES/plone.po create mode 100644 src/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po create mode 100644 src/pcommerce/core/locales/nl/LC_MESSAGES/plone.po create mode 100644 src/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po create mode 100644 src/pcommerce/core/locales/no/LC_MESSAGES/plone.po create mode 100644 src/pcommerce/core/locales/pcommerce.pot create mode 100644 src/pcommerce/core/locales/plone.pot create mode 100644 src/pcommerce/core/order.py create mode 100644 src/pcommerce/core/permissions.zcml create mode 100644 src/pcommerce/core/plone3.py create mode 100644 src/pcommerce/core/processor.py create mode 100644 src/pcommerce/core/profiles/default/.propertiestool.xml.swp create mode 100644 src/pcommerce/core/profiles/default/actions.xml create mode 100644 src/pcommerce/core/profiles/default/catalog.xml create mode 100644 src/pcommerce/core/profiles/default/controlpanel.xml create mode 100644 src/pcommerce/core/profiles/default/cssregistry.xml create mode 100644 src/pcommerce/core/profiles/default/factorytool.xml create mode 100644 src/pcommerce/core/profiles/default/jsregistry.xml create mode 100644 src/pcommerce/core/profiles/default/metadata.xml create mode 100644 src/pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt create mode 100644 src/pcommerce/core/profiles/default/portlets.xml create mode 100644 src/pcommerce/core/profiles/default/propertiestool.xml create mode 100644 src/pcommerce/core/profiles/default/rolemap.xml create mode 100644 src/pcommerce/core/profiles/default/skins.xml create mode 100644 src/pcommerce/core/profiles/default/types.xml create mode 100644 src/pcommerce/core/profiles/default/types/Folder.xml create mode 100644 src/pcommerce/core/profiles/default/types/Price.xml create mode 100644 src/pcommerce/core/profiles/default/types/Product.xml create mode 100644 src/pcommerce/core/profiles/default/types/Variation.xml create mode 100644 src/pcommerce/core/profiles/default/viewlets.xml create mode 100644 src/pcommerce/core/registry.py create mode 100644 src/pcommerce/core/required.py create mode 100644 src/pcommerce/core/setuphandlers.py create mode 100644 src/pcommerce/core/skins/pcommerce/pcommerce.css.dtml create mode 100644 src/pcommerce/core/steps.py create mode 100644 src/pcommerce/core/vocabulary.py diff --git a/src/pcommerce/__init__.py b/src/pcommerce/__init__.py new file mode 100644 index 0000000..f48ad10 --- /dev/null +++ b/src/pcommerce/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/src/pcommerce/core/__init__.py b/src/pcommerce/core/__init__.py new file mode 100644 index 0000000..54cb61a --- /dev/null +++ b/src/pcommerce/core/__init__.py @@ -0,0 +1,26 @@ +"""Main product initializer +""" + +from pcommerce.core.config import PROJECTNAME, permissions + +from Products.Archetypes import atapi +from Products.CMFCore import utils as cmfutils +from Products.CMFCore.utils import getToolByName + +from zope.i18nmessageid import MessageFactory +PCommerceMessageFactory = MessageFactory('pcommerce') + +def initialize(context): + + from content import product, variation, price + + content_types, constructors, ftis = atapi.process_types( + atapi.listTypes(PROJECTNAME), + PROJECTNAME) + + for atype, constructor in zip(content_types, constructors): + cmfutils.ContentInit("%s: %s" % (PROJECTNAME, atype.portal_type), + content_types = (atype,), + permission = permissions[atype.portal_type], + extra_constructors = (constructor,), + ).initialize(context) \ No newline at end of file diff --git a/src/pcommerce/core/adapters.py b/src/pcommerce/core/adapters.py new file mode 100644 index 0000000..84d0107 --- /dev/null +++ b/src/pcommerce/core/adapters.py @@ -0,0 +1,150 @@ +from Acquisition import aq_parent + +from zope.interface import implements, Interface +from zope.component import adapts, getMultiAdapter +from zope.annotation.interfaces import IAnnotations + +from Products.CMFCore.utils import getToolByName +from Products.ATContentTypes.interface.image import IImageContent + +from pcommerce.core import interfaces + +ANNOTATIONS_KEY_TAXES = 'pcommerce.core.taxes' +ANNOTATIONS_KEY_TAX_INCLUDED = 'pcommerce.core.tax_included' + +class Imaging(object): + """ An adapter to handle the images of a product + """ + implements(interfaces.IImaging) + adapts(interfaces.IProduct) + + def __init__(self, context): + self.context = context + + def getImages(self): + """ All image inside of the product + """ + catalog = getToolByName(self.context, 'portal_catalog') + images = catalog(object_provides=IImageContent.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), + 'depth': 1}) + return images + +class Pricing(object): + """ An adapter to handle prices of a product + """ + implements(interfaces.IPricing) + adapts(interfaces.IProduct) + + def __init__(self, context): + self.context = context + + def getPrice(self, variations=[]): + """ The product price in combination of variations + """ + price = 0 + if self.context.getPrice() is not None: + price = float(self.context.getPrice()) + catalog = getToolByName(self.context, 'portal_catalog') + prices = [float(p.getPrice or 0) for p in catalog(object_provides=interfaces.IPrice.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()),'depth': 1})] + prices.append(price) + if len(prices)>0: + price = min(prices) + add = 0 + prices = [] + if len(variations): + for variation in variations: + if variation.getAddPrice(): + add += float(variation.getPrice()) + else: + v_prices = [float(v.getPrice or 0) for v in catalog(object_provides=interfaces.IPrice.__identifier__, path={'query': '/'.join(variation.getPhysicalPath()),'depth': 1})] + if variation.getPrice() is not None: + v_prices.append(float(variation.getPrice())) + if len(v_prices)>0: + prices.append(min(v_prices)) + + if len(prices)>0 and float(price) < float(max(prices)): + price = max(prices) + return float(price) + float(add) + + def getBasePrice(self, variations=[]): + """ The base price defined on the product + """ + return float(self.context.getPrice() or 0) + +class Taxes(object): + """ An adapter to handle taxes based on zones + + len(Taxes) + Taxes.has_key(key) + Taxes.items() + Taxes[key] + Taxes[key] = value + del(Taxes[key]) + """ + implements(interfaces.ITaxes) + adapts(Interface) + + _items = {} + _taxincl = None + + def __init__(self, context): + self.context = context + self.portal = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').portal() + annotations = IAnnotations(self.portal) + self._items = dict(annotations.get(ANNOTATIONS_KEY_TAXES, ())) + self._taxincl = annotations.get(ANNOTATIONS_KEY_TAX_INCLUDED, None) + + def __len__(self): + return len(self._items) + + def __getitem__(self, key): + return self._items[key] + + def __setitem__(self, key, value): + if not isinstance(value[0], float): + raise AttributeError, 'value has to be a float got %s' % type(value[0]) + self._items[key] = value + self._save() + + def __delitem__(self, key): + del(self._items[key]) + self._save() + + def has_key(self, key): + return self._items.has_key(key) + + def items(self): + return self._items.items() + + def keys(self): + return self._items.keys() + + def get_taxincl(self): + return self._taxincl + + def set_taxincl(self, value): + self._taxincl = value + annotations = IAnnotations(self.portal) + annotations[ANNOTATIONS_KEY_TAX_INCLUDED] = self._taxincl + + def del_taxincl(self): + del self._taxincl + annotations = IAnnotations(self.portal) + annotations[ANNOTATIONS_KEY_TAX_INCLUDED] = None + + taxincl = property(get_taxincl, set_taxincl, del_taxincl, "I'm the 'tax_incl' property.") + + + def edit(self, taxes): + """ edits the taxes + + taxes has to be a list of dicts with keys 'zone', 'tax' and 'taxname' + """ + self._items = {} + self._save() + for tax in taxes: + self[tax['zone']] = (tax['tax'], tax['taxname']) + + def _save(self): + annotations = IAnnotations(self.portal) + annotations[ANNOTATIONS_KEY_TAXES] = self.items() diff --git a/src/pcommerce/core/address.py b/src/pcommerce/core/address.py new file mode 100644 index 0000000..52e2219 --- /dev/null +++ b/src/pcommerce/core/address.py @@ -0,0 +1,108 @@ +import re +from persistent import Persistent + +from zope.i18n import translate +from zope.interface import implements, Interface +from zope.component import adapts + +from Products.CMFPlone import PloneMessageFactory as _p +from Products.validation.validators.BaseValidators import EMAIL_RE +email_re = re.compile(EMAIL_RE) + +from pcommerce.core.interfaces import IAddress, IAddressFactory +from pcommerce.core import PCommerceMessageFactory as _ + +class Address(Persistent): + """""" + implements(IAddress) + + salutation = u'' + firstname = u'' + lastname = u'' + company = u'' + address1 = u'' + address2 = u'' + zip = u'' + city = u'' + country = u'' + zone = u'' + email = u'' + phone = u'' + + def __init__(self, + salutation, + firstname, + lastname, + company, + address1, + address2, + zip, + city, + country, + zone, + email, + phone): + """""" + self.salutation = salutation + self.firstname = firstname + self.lastname = lastname + self.company = company + self.address1 = address1 + self.address2 = address2 + self.zip = zip + self.city = city + self.country = country + self.zone = zone + self.email = email + self.phone = phone + + def mailInfo(self, request, lang=None, customer=False): + address = [(self.salutation and translate((self.salutation == 'mr' and _('Mr.') or _('Mrs. / Ms.')), context=request, target_language=lang) +' ' or '') + self.firstname +' '+ self.lastname, + self.company, + self.address1, + self.address2, + self.zip + (self.zip is not None and ' ') + self.city, + self.country, + self.zone] + address = [value for value in address if value] + address.append('') + address.append(self.email) + if self.phone: + address.append(self.phone) + return '\n'.join(address) + +class AddressFactory(object): + adapts(Interface) + implements(IAddressFactory) + + required = ('firstname', 'lastname', 'address1', 'city', 'country', 'phone') + + def __init__(self, request): + self.request = request + + def validate(self, tag): + errors = {} + required = self.required + data = self.request.get(tag, {}) + for field in required: + if not data.get(field, None): + errors[tag+'.'+field] = _p(u'This field is required, please provide some information.') + + if not email_re.match(data.get('email', '')): + errors[tag+'.'+'email'] = _p(u'Please submit a valid email address.') + return errors + + def create(self, tag): + data = self.request.get(tag, {}) + return Address(salutation = data.get('salutation', '').decode('utf-8'), + firstname = data.get('firstname', '').decode('utf-8'), + lastname = data.get('lastname', '').decode('utf-8'), + company = data.get('company', '').decode('utf-8'), + address1 = data.get('address1', '').decode('utf-8'), + address2 = data.get('address2', '').decode('utf-8'), + zip = data.get('zip', '').decode('utf-8'), + city = data.get('city', '').decode('utf-8'), + country = data.get('country', '').decode('utf-8'), + zone = data.get('zone', '').decode('utf-8'), + email = data.get('email', '').decode('utf-8'), + phone = data.get('phone', '').decode('utf-8'),) diff --git a/src/pcommerce/core/browser/.configlet.pt.swp b/src/pcommerce/core/browser/.configlet.pt.swp new file mode 100644 index 0000000000000000000000000000000000000000..a53e0a0ece8e45f84924dc21b30a5aaa02b38e47 GIT binary patch literal 24576 zcmeI3ZLA$d8OK+wfXbUCDg@E((d4wiJ=<$zq?dDw(zF((r1S-$rJU?JJNKMT_w25_ zbMC#pG@=Ox!Iy}BQKGgr!ALO1#6m*+0MQtuen2DyBzypZ3Bm_sKnan6|7T`*&(6M_ zds^?MMfN7YyJvT2W@nz6XJ(#fW;*Myzk0j=>Ba^Pf9GkM{;z-Rcyaa3+UECbTF)D> zMS8x(-=a6@*b9TkY+&=nM#ozy3IAo0pkc8&!?&Hqsj%B047&#!7Bj-2YxrGnFknHK zHM(BFMz@Bz?F8O@$O7EBvv$v6yy5eb?^KT~2~-luNMOikr!GHR+wjTh_4MZBwKe+r ztM_CARkxJ{DhX5)s3cHHpprl(fl30E1S$#qKTCl7tF&8Dz|*2avgrD*%=JCdeJi@o zX5O!g?k|h3cV^zdJG$Q*UGLAlk8Z0=C4ou;l>{mYR1&BpP)VSYKqY}n0+j?R2~-lO zB(MS!FfC16hjjl+20zySWBdQ{b2aS<=z;ZMHF)eCO*;mD1%3|h1BbvZ;7V{2I2)V= zUOQXUo&tA)0JMM(&IhZ(YiDWNBjAVNE8s>@121FW!E@lZ;0EwT&;YBz^Y7ENKY>4j zAA@OHV(=00 zGMq2J2ls$)f^Pr@THv3km!|;L&y!R~6aVR%zouc?bDOlxQ*pby&vf79eVuzc7r%Rq zes`E2Fv|{DmotkVn6sP(dbiKI2fQIKOiQRhx@!(l|Kg`e1Z_d*2Yo!_Y=NsqqI{)GJ#Sk*#vvA^tRmF-cD#jz zpNm8hMeSkx5N9rL)np|p#mbjTiXqL@w&qZ^RwVkbG6cg2W+}X{kUEgyo$XMuM zkGU)`9UV$H2t~6=@(~Jk>~@*Yp{8i(q`?OVC|YsZ-y*I2-0scA-;Z>W8bg7YS6Tx_ z<-9%g&JR3m*yW@9#U2!gQ zW1P^tHg)+Ft3Wd;Rb56)k9(p3A+H3n>z8)#6g*gEgt_ z$;^QU#!*;Jer@!B{Pba@X1Rz_5_0k|3RfVW=1O;5N_+j^J1{C)rnsax7MrzQ49jv% z)5Wkaf9J{^&Dt<4O?YMp*caazqgH1Ozz>$1{*NU zq$nt+Y}t3&>53^nl+0K5?7Sw|0+C!&x~YNL4ZK!uV204uQQ}Qe3Yl1|)<})uO~X{x zY>!Wa?k<}%eHY_HKV8PGf=kUB`fcvDMVoJj6h)P%h*Yi_*%J2yHmir2eY(9F{S&?y zAV7NF|tX+uSrGb$jeJgPLub`MPXW`Ie;=ylW7DP7FXMst^@(Vtd}zGHK= zH(Qr=Hw;Xw=0pO`{&f5m%j*tl96`Q72jvHsazyY3AQ;K_++6NqG5!%q#MS< zz?pGOw+E%bh?x9}3XHdII72yT)%u+KGlqdjjYZFA4KL^!G)|za>ax(FK(VxCG?B9< z zU;YC2{&&GVcmekO_rN^32|Nz_{Wj1C+ra~{+wTUq0t37NTm3iSN8qcV2d)7dz(wF3 z@G5NfpMq}#4)%dH;BT;+eXmtdD40gGS{ z*a$ubR)Lpbo0Gl%7jQQifDeG@P;Ro*?*MaP2pF)yKCl<;1fK^aqivx2t0YiKAS(e3 z8t73rX-y;PrXwH3Xp}H$uuXb!UHp|eDw;<5JXc1{PfMi-Lk_*6Imc>xiKil+K>7F^ zg~Bi;9UIc0F`CB6PsApa_+B*9(ojq;j>z2+4m$%oHRi?%E7Msy1-WX-x#xz-FeZbF zagydxGEjIu95c0ez$KY(mSaD~)8f?W+BAey3Ud#2JeTh{P2KV@C>ocQm`*GHjh8`D zq$o|R?43v!^D!~AEDuDN~>Aeu&o&^Yk7eMGp^^tecpyS$Pd=^NXL;snms^Cs4p&PXr^VMnbS)s znV52@tt#ovkwl5|iUG0oU6MfYXb^XO$fy_$j=#%;6wud~h=J4?>on%V*ic0sqJC0_ zhm1HV`zJ6K%ED6Q$;2`y z6g&?fz|X+fK_6TTHh>Gk6DhyIoA3oZ1onap!0WL4p9Ma+6r2lQfz5wA*a|KIw3gq4 zt^WnE9y|>@|1NL<(3<@v;5_gm?EPDT1w`Jn=16s4NuZKIC4ou;?|2C$GpWoE)egqk zPov`m1OJ#{MWeo!`D}DMW?G04*-77IJB`GwdV*!bI7cwY5-(DIn^6+#?c?ylgmqut zw(9$r)8UgOy3z&L1E zQ!hsCTq&j&cTpwRY%eO>1^U(n!?q^Lr1T*4ZOfunU=n+*pdC?ul!Z%r zJjwn)1MA=)j_m*VeE%`n`61W?Hh~tn06YvEe>Z4>OTfk84cPoY0N)25*bLTyGr<|) zS=jy$0t;*h*8mMX1pEIexD(s~EN~V$0w2H~U=A>_1^gMlfJeZ+;4|P+_yFd?&EO_5 z4PJ*Y;8E}ZxF38AbisMxRg~}F;3${{Tfr2#3|t7P{Io})jq9(m#(x;x2A;;=h=;*F z;5u+Rc;+;O0f)iYKpVUg?a{w6-lHFDUG|zA(bBzK#uu6HaK;2H8trloMdo7#`l5O@ z>5O~hYSKxAs`QyxlTNV#VA-AFiehIsSd2QGqFogeMiq%n7`Es$NhX$D#i!|6vT`ps zoEl4Q_Qvo#`F3ww*y-8WGAVW|wz1s9g2H{@v=mc%JWAJh^}V5k6HwTeAkv^^MQrZF znT$Ep#tJ1JG}2wq)pyYLW}Ho;t(p3EHt4XDvnbJ~YGvtFk-3zjC~LH-g!XxqoRp&M zk6nYhRuP0OM8W5xs>7FBwIbOS?xHB&1fAV#OsS6*bM*P_tX){NSk8_1cE}|<>E(!C zMaQVh4kqEVqoYZM<%;I^>bsea=Q+&8%s(1o^ES2?WjTAHBE-9@rO}Z-OQn8BHp^r; zN72h-xu;IiMaQMo%|9|zIcd_lyI7W`XV!{xG11XAYSUB&twHKzhr$J zovV^$VXr!-4ry!<3FuK3VIzN+*>iNPhR#QZ*xo_ElihZBPrJ1(8S5=LW;3Qg-9l|E z&bZQ;Q_WL!qKb?Pw79hI%%_@d?vr_hMFu8P+;pof&|4)#B^6upI3<*9Ayl1J4$3Mz ctG=0BXO(!d&SoB-vO25eb9r=DNs@H-zZ342O8@`> literal 0 HcmV?d00001 diff --git a/src/pcommerce/core/browser/__init__.py b/src/pcommerce/core/browser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/browser/address.pt b/src/pcommerce/core/browser/address.pt new file mode 100644 index 0000000..a8bc1a3 --- /dev/null +++ b/src/pcommerce/core/browser/address.pt @@ -0,0 +1,348 @@ + +
    + +
    + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    + + + +
    + The Error +
    + +
    + + +
    +
    + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + +
    + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + + (Required) + + +
    + The Error +
    + +
    + The Error +
    + +
    +
    + + + +
    +
    +
    + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + + + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    + +
    + + + + + (Required) + + +
    + The Error +
    + +
    + +
    +
    +
    +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/cart.pt b/src/pcommerce/core/browser/cart.pt new file mode 100644 index 0000000..3c08110 --- /dev/null +++ b/src/pcommerce/core/browser/cart.pt @@ -0,0 +1,131 @@ + + + + + + +

    + Your shopping cart +

    + +

    + Your shopping cart is empty +

    + +
    + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ProductAmountPricePrice totalRemove
    + + + + + + + 50.00 + + 500.00 + + +
    + Total + +   + +   + + + 500.00 + + +   +
    +

    + You have to be registered to check out your order, either + + log in + if you already + have an account or head over to the + + registration form + if you don't. +

    +
    + + +
    +
    + +
    +
    + + + diff --git a/src/pcommerce/core/browser/cart.py b/src/pcommerce/core/browser/cart.py new file mode 100644 index 0000000..39fdd9b --- /dev/null +++ b/src/pcommerce/core/browser/cart.py @@ -0,0 +1,49 @@ +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from plone.memoize.instance import memoize + +from Products.CMFCore.utils import getToolByName + +from pcommerce.core.currency import CurrencyAware +from pcommerce.core.config import CheckOut +from pcommerce.core.interfaces import IShoppingCart, ITaxes + +class Cart(BrowserView): + """view of the shopping cart + """ + + template = ViewPageTemplateFile('cart.pt') + + def __call__(self): + self.request.set('disable_border', 1) + self.cart = IShoppingCart(self.context) + return self.template() + + @property + @memoize + def size(self): + return self.cart.amount() + + @property + @memoize + def products(self): + return self.cart.getProducts() + + @property + @memoize + def checkout(self): + return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) + + @property + @memoize + def price(self): + return CurrencyAware(self.cart.getPrice()) + + @property + @memoize + def taxincl(self): + taxes = ITaxes(self.context) + return {'tax': taxes.taxincl[0], + 'taxname': taxes.taxincl[1]} + \ No newline at end of file diff --git a/src/pcommerce/core/browser/checkout.pt b/src/pcommerce/core/browser/checkout.pt new file mode 100644 index 0000000..60dafc6 --- /dev/null +++ b/src/pcommerce/core/browser/checkout.pt @@ -0,0 +1,72 @@ + + + + +
    + +

    + Check out +

    +
    + + + + + + +
    +
    +
    +
    +
    +
    + + + + + + + +
    + + + +
    + +
    + +
    + + + +
    + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/checkout.py b/src/pcommerce/core/browser/checkout.py new file mode 100644 index 0000000..37f0525 --- /dev/null +++ b/src/pcommerce/core/browser/checkout.py @@ -0,0 +1,376 @@ +import re + +from zope.component import getMultiAdapter +from zope.interface import implements + +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.CMFCore.utils import getToolByName +from Products.statusmessages.interfaces import IStatusMessage +from Products.validation.validators.BaseValidators import EMAIL_RE +email_re = re.compile(EMAIL_RE) + +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.config import INITIALIZED +from pcommerce.core.interfaces import IShoppingCart, IOrderRegistry, ISteps +from pcommerce.core.interfaces import ICheckoutView, IComponent, IOrder + +from pcommerce.core.order import ORDER_SESSION_KEY + + +class Checkout(BrowserView): + """checkout view + """ + implements(ICheckoutView) + + template = ViewPageTemplateFile('checkout.pt') + + errors = {} + cart = None + order = None + stepid = 0 + components = [] + redirect = None + + def __call__(self): + self.request.set('disable_border', 1) + self.errors = {} + + self.cart = IShoppingCart(self.context) + + if not len(self.cart): + statusmessage = IStatusMessage(self.request) + statusmessage.addStatusMessage(_(u'You have not yet added any ' + 'products to your cart'), 'error') + return self.request.RESPONSE.redirect('%s/@@cart' % + self.context.absolute_url()) + + if self.request.form.get('checkout.cancel', None): + return getMultiAdapter((self.context, self.request), + name=u'checkout.cancel')() + + self.stepid = int(self.request.form.get('checkout.stepid', 0)) + + temp_state = None + registry = IOrderRegistry(self.context) + self.order = registry.getOrder(self.request.SESSION.get( + ORDER_SESSION_KEY, 0)) + if self.order is not None and self.order.state != INITIALIZED: + temp_state = self.order.state + self.order.state = INITIALIZED + + self.order = IOrder(self.context) + + self._stepid_validator() + + if self.request.form.get('checkout.next') and \ + self.stepid < len(self.steps) - 1: + self.next() + elif self.request.form.get('checkout.previous') and self.stepid > 0: + self.previous() + elif self.request.get('stepid'): + self.gotostep(int(self.request.get('stepid', 0))) + + if self.redirect is not None: + return self.request.RESPONSE.redirect(self.redirect) + + html = self.template() + + if temp_state is not None: + self.order.state = temp_state + + if self.laststep: + registry = IOrderRegistry(self.context) + registry.send(self.order.orderid) + self.cart.clear() + return html + + @property + def steps(self): + return ISteps(self.context) + + def next(self): + self._nextstep() + while 1: + for component in self.components: + if component.renders(): + return + self._nextstep() + + def previous(self): + self._previousstep() + while 1: + for component in self.components: + if component.renders(): + return + self._previousstep() + + def gotostep(self, stepid): + self._gotostep(stepid) + renders = False + for component in self.components: + if component.renders(): + renders = True + if not renders: + self.gotostep(self.stepid + 1) + + def _nextstep(self): + if self.validate(): + self.process() + self.stepid += 1 + self._stepid_validator() + + def _previousstep(self): + self.stepid -= 1 + self._stepid_validator() + + def _gotostep(self, stepid): + self.stepid = stepid + self._stepid_validator() + + def _stepid_validator(self): + if self.stepid < 0: + self.stepid = 0 + self._initialize_components() + return + elif self.stepid > len(self.steps) - 1: + self.stepid = len(self.steps) - 1 + + for stepid in range(0, self.stepid): + if not stepid in self.order.processed_steps: + self.stepid = stepid + self._initialize_components() + return + + self._initialize_components() + + def _initialize_components(self): + self.components = [] + for name in self.steps[self.stepid]['components']: + component = getMultiAdapter((self.context, self.request), + interface=IComponent, name=name).__of__(self.context) + self.components.append(component) + return self.components + + def validate(self): + valid = True + for component in self.components: + if not component.validate(): + valid = False + return valid + + def process(self): + self.redirect = None + for component in self.components: + component.process() + if not (self.stepid in self.order.processed_steps): + self.order.processed_steps = self.order.processed_steps + \ + (self.stepid,) + for i in range(0, len(self.steps)): + step = self.steps[i] + for name in step['components']: + s_component = getMultiAdapter( + (self.context, self.request), interface=IComponent, + name=name).__of__(self.context) + if component.__name__ in s_component.dependencies: + self.order.processed_steps = \ + tuple([n for n in self.order.processed_steps + if not n == i]) + if hasattr(component, 'action'): + action = component.action() + if action: + self.redirect = action + + def renders(self, step): + components = [] + for name in step['components']: + component = getMultiAdapter((self.context, self.request), + interface=IComponent, name=name).__of__(self.context) + if component.renders(): + return True + return False + + @property + def stepnavigation(self): + steps = [] + step = None + + for i in range(0, len(self.steps)): + step = self.steps[i] + if len(steps) and step['name'] == steps[-1]['name']: + continue + renders = False + for name in step['components']: + component = getMultiAdapter((self.context, self.request), + interface=IComponent, name=name).__of__(self.context) + if component.renders(): + renders = True + if not renders: + continue + + selected = False + if step['name'] == self.steps[self.stepid]['name']: + selected = True + + _class = 'step' + if i == 0: + _class += ' first' + elif i == (len(self.steps) - 1): + _class += ' last' + if selected: + _class += ' select' + if i < self.stepid: + _class += ' passed' + if i in self.order.processed_steps: + _class += ' processed' + href = None + if (i in self.order.processed_steps or \ + (i - 1) in self.order.processed_steps) and \ + not selected and not self.laststep: + href = '%s/@@checkout?stepid=%s' % ( + self.context.absolute_url(), i) + + steps.append({'stepid': str(i), + 'name': step['name'], + 'selected': selected, + 'href': href, + 'class': _class, }) + return steps + + @property + def previous_label(self): + for component in self.components: + if hasattr(component, 'previous_label'): + return component.previous_label + if self.laststep: + return _(u'Print') + return _(u'Previous step') + + @property + def next_label(self): + for component in self.components: + if hasattr(component, 'next_label'): + return component.next_label + if self.laststep: + return _(u'Continue shopping') + if self.stepid == len(self.steps) - 2: + return _(u'Send order') + return _(u'Next step') + + @property + def cancel_label(self): + for component in self.components: + if hasattr(component, 'cancel_label'): + return component.cancel_label + return _(u'Cancel checkout') + + @property + def previous_onclick(self): + for component in self.components: + if hasattr(component, 'previous_onclick'): + return component.previous_onclick + if self.laststep: + return "print()" + return None + + @property + def next_onclick(self): + for component in self.components: + if hasattr(component, 'next_onclick'): + return component.next_onclick + return None + + @property + def cancel_onclick(self): + for component in self.components: + if hasattr(component, 'cancel_onclick'): + return component.cancel_onclick + return None + + @property + def action(self): + if self.laststep: + props = getToolByName(self.context, + 'portal_properties').pcommerce_properties + portal_state = getMultiAdapter((self.context, self.request), + name=u'plone_portal_state') + return '%s/%s' % (portal_state.portal_url(), + props.getProperty('post_checkout', '')) + return self.context.absolute_url() + '/@@checkout' + + @property + def laststep(self): + return self.stepid == len(self.steps) - 1 + + +class PaymentFailed(BrowserView): + """ Payment failed + """ + + def __call__(self): + order = IOrder(self.context) + m = len(order.processed_steps) and max(order.processed_steps) or 0 + order.processed_steps = tuple( + [n for n in order.processed_steps if n != m]) + statusmessage = IStatusMessage(self.request) + statusmessage.addStatusMessage(_(u'Payment failed'), 'error') + return self.request.RESPONSE.redirect('%s/@@checkout?stepid=%s' % ( + self.context.absolute_url(), m)) + + +class PaymentCancel(BrowserView): + """ Payment canceled + """ + + def __call__(self): + order = IOrder(self.context) + m = len(order.processed_steps) and max(order.processed_steps) or 0 + order.processed_steps = tuple( + [n for n in order.processed_steps if n != m]) + statusmessage = IStatusMessage(self.request) + statusmessage.addStatusMessage(_(u'Payment canceled'), 'error') + return self.request.RESPONSE.redirect('%s/@@checkout?stepid=%s' % ( + self.context.absolute_url(), m)) + + +class PaymentSuccess(BrowserView): + """ Payment successful + """ + + def __call__(self): + registry = IOrderRegistry(self.context) + order = registry.getOrder( + self.request.SESSION.get(ORDER_SESSION_KEY, 0)) + return self.request.RESPONSE.redirect( + '%s/@@checkout?checkout.stepid=%s' % ( + self.context.absolute_url(), + max(order.processed_steps) + 1)) + + +class CheckoutCancel(BrowserView): + """checkout cancel view + """ + + def __call__(self): + registry = IOrderRegistry(self.context) + registry.cancel(self.request.SESSION.get(ORDER_SESSION_KEY, 0)) + statusmessage = IStatusMessage(self.request) + statusmessage.addStatusMessage( + _('message_checkout_canceled', default=u'Check out canceled'), + 'info') + return self.request.RESPONSE.redirect('%s/@@cart' % + self.context.absolute_url()) + + +class CheckoutFailed(BrowserView): + """checkout failed view + """ + + def __call__(self): + registry = IOrderRegistry(self.context) + registry.fail(self.request.SESSION.get(ORDER_SESSION_KEY, 0)) + statusmessage = IStatusMessage(self.request) + statusmessage.addStatusMessage(_('message_checkout_failed', + default=u'Check out failed'), 'error') + return self.request.RESPONSE.redirect( + '%s/@@cart' % self.context.absolute_url()) diff --git a/src/pcommerce/core/browser/components/__init__.py b/src/pcommerce/core/browser/components/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/browser/components/address.pt b/src/pcommerce/core/browser/components/address.pt new file mode 100644 index 0000000..1e050f3 --- /dev/null +++ b/src/pcommerce/core/browser/components/address.pt @@ -0,0 +1,17 @@ + +
    +

    + Billing address +

    + +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/address.py b/src/pcommerce/core/browser/components/address.py new file mode 100644 index 0000000..fb0d66b --- /dev/null +++ b/src/pcommerce/core/browser/components/address.py @@ -0,0 +1,26 @@ +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.CMFPlone import PloneMessageFactory as _p + +from pcommerce.core.browser.components.base import BaseComponent +from pcommerce.core import interfaces + +class AddressComponent(BaseComponent): + index = ViewPageTemplateFile('address.pt') + + def validate(self): + self.errors = {} + factory = interfaces.IAddressFactory(self.request) + self.errors = factory.validate('customer') + return len(self.errors) == 0 + + def process(self): + factory = interfaces.IAddressFactory(self.request) + self.order.address = factory.create('customer') + taxes = interfaces.ITaxes(self.context) + if self.order.address.zone and taxes.has_key(self.order.address.zone): + self.order.zone = (self.order.address.zone, taxes[self.order.address.zone]) + + @property + def address(self): + return self.order.address + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/base.py b/src/pcommerce/core/browser/components/base.py new file mode 100644 index 0000000..2913e91 --- /dev/null +++ b/src/pcommerce/core/browser/components/base.py @@ -0,0 +1,273 @@ +from zope.interface import implements, Interface +from zope.component import adapts, getMultiAdapter, queryMultiAdapter, getAdapter + +from plone.memoize.instance import memoize + +from Products.Five.browser import BrowserView + +from pcommerce.core import interfaces +from pcommerce.core.currency import CurrencyAware + +class BaseComponent(BrowserView): + implements(interfaces.IComponent) + adapts(Interface) + + errors = {} + cart = None + order = None + dependencies = () + + def __init__(self, context, request): + self.context = context + self.request = request + self.order = interfaces.IOrder(self.context) + self.cart = interfaces.IShoppingCart(self.context) + + def __call__(self): + return self.index() + + def _shipments(self): + registry = interfaces.IShipmentRegistry(self.context) + return registry.getShipmentMethods() + + def _shipmentgroups(self): + groups = {} + products = self.products + available_shipmentids = self._shipments() + for product in products: + product = product['object'] + shipmentids = product.getShipments() + shipmentids = [shipmentid for shipmentid in shipmentids if shipmentid in available_shipmentids] + shipmentids.sort() + shipmentids = tuple(shipmentids) + if groups.has_key(shipmentids): + groups[shipmentids].append(product) + else: + groups[shipmentids] = [product,] + return groups + + @property + def shipmentgroups(self): + group = [] + shipmentgroups = self._shipmentgroups() + shipments = self._shipments() + for shipmentids, products in shipmentgroups.items(): + mapping = [] + for id in shipmentids: + if shipments.has_key(id): + shipment = shipments[id] + + # check is selected + selected = False + uids = [] + for product in products: + uids.append(product.UID()) + uids = tuple(uids) + for shipment_id, products_uids in self.order.shipmentids.items(): + if shipment_id == id and products_uids == uids: + selected = True + break + + mapping.append({'id': id, + 'title': shipment.title, + 'description': shipment.description, + 'icon': shipment.icon, + 'logo': shipment.logo, + 'selected': selected}) + group.append({'shipments': mapping, + 'products': products, + 'shipmentids': shipmentids, }) + return group + + @property + @memoize + def shipments(self): + shipments =[] + i = 1 + for shipmentid, products in self.order.shipmentids.items(): + shipment = getAdapter(self.context, name=shipmentid, interface=interfaces.IShipmentMethod) + data = {'id': shipmentid, + 'plugin': shipment, + 'title': shipment.title, + 'description': shipment.description, + 'icon': shipment.icon, + 'logo': shipment.logo, + 'products': products, + 'renders': False, + 'view': None, + 'number': i} + shipmentview = queryMultiAdapter((shipment, self.request), name=self.__name__, interface=interfaces.IShipmentView) + if shipmentview is not None: + data['view'] = shipmentview.__of__(self.context) + data['renders'] = data['view'].renders() + shipments.append(data) + i += 1 + return shipments + + def _payments(self): + registry = interfaces.IPaymentRegistry(self.context) + return registry.getPaymentMethods() + + @property + def payments(self): + payments = [] + for name, payment in self._payments().items(): + selected = False + if name == self.order.paymentid: + selected = True + payments.append({'id': name, + 'plugin': payment, + 'title': payment.title, + 'description': payment.description, + 'icon': payment.icon, + 'logo': payment.logo, + 'selected': selected}) + return payments + + @property + def payment(self): + payment = self._payments().get(self.order.paymentid, None) + if payment is None: + return None + data = {'id': self.order.paymentid, + 'plugin': payment, + 'title': payment.title, + 'description': payment.description, + 'icon': payment.icon, + 'logo': payment.logo, + 'view': None} + view = queryMultiAdapter((payment, self.request), name=self.__name__, interface=interfaces.IPaymentView) + if view is not None: + data['view'] = view.__of__(self.context) + return data + + @property + @memoize + def paymentview(self): + return self.payment and self.payment['view'] or None + + def action(self): + if self.paymentview is not None: + if hasattr(self.paymentview, 'action'): + return self.paymentview.action() + return None + + @property + def products(self): + return self.cart.getProducts() + + def getProductNumber(self, uid): + if len(self.shipments) == 1: + return None + for shipment in self.shipments: + if uid in shipment['products']: + return shipment['number'] + return None + + @property + def price(self): + if self.order: + return CurrencyAware(self.order.price) + return CurrencyAware(self.cart.getPrice()) + + @property + def pricetax(self): + if self.order: + return CurrencyAware(self.order.pricetax) + return None + + @property + def pricetaxincl(self): + if self.order: + return CurrencyAware(self.order.pricetaxincl) + return None + + @property + def pretaxcharges(self): + charges = [] + if getattr(self.order.paymentdata, 'pretaxcharge', 0): + charges.append({'title': self.payment['title'], + 'price': CurrencyAware(getattr(self.order.paymentdata, 'pretaxcharge', 0))}) + for shipmentid, data in self.order.shipmentdata.items(): + if not data.pretaxcharge: + continue + for shipment in self.shipments: + if shipmentid == shipment['id']: + charges.append({'title': shipment['title'], + 'number': len(self.shipments) > 1 and shipment['number'] or None, + 'price': CurrencyAware(data.pretaxcharge)}) + for charge in self.order.pretaxcharges: + if charge.price: + charges.append({'title': charge.title, + 'price': CurrencyAware(charge.price)}) + return charges + + @property + def subtotal(self): + if self.order.pretaxcharge: + return CurrencyAware(self.order.subtotal) + return None + + @property + def posttaxcharges(self): + charges = [] + if getattr(self.order.paymentdata, 'posttaxcharge', 0): + charges.append({'title': self.payment['title'], + 'price': CurrencyAware(getattr(self.order.paymentdata, 'posttaxcharge', 0))}) + for shipmentid, data in self.order.shipmentdata.items(): + if not data.posttaxcharge: + continue + for shipment in self.shipments: + if shipmentid == shipment['id']: + charges.append({'title': shipment['title'], + 'number': len(self.shipments) > 1 and shipment['number'] or None, + 'price': CurrencyAware(data.posttaxcharge)}) + for charge in self.order.posttaxcharges: + if charge.price: + charges.append({'title': charge.title, + 'price': CurrencyAware(charge.price)}) + return charges + + @property + def totalincl(self): + if self.order.posttaxcharge: + return CurrencyAware(self.order.totalincl) + return None + + @property + def taxincl(self): + if self.order: + return self.order.taxincl + return None + + @property + def taxinclname(self): + if self.order: + return self.order.taxinclname + return None + + @property + def tax(self): + if self.order: + return self.order.tax + return None + + @property + def taxname(self): + if self.order: + return self.order.taxname + return None + + @property + def total(self): + if self.order: + return CurrencyAware(self.order.total) + return None + + @property + def zones(self): + taxes = interfaces.ITaxes(self.context) + return taxes.keys() + + def renders(self): + return True diff --git a/src/pcommerce/core/browser/components/configure.zcml b/src/pcommerce/core/browser/components/configure.zcml new file mode 100644 index 0000000..bd6f987 --- /dev/null +++ b/src/pcommerce/core/browser/components/configure.zcml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/browser/components/confirmation.pt b/src/pcommerce/core/browser/components/confirmation.pt new file mode 100644 index 0000000..f79c22b --- /dev/null +++ b/src/pcommerce/core/browser/components/confirmation.pt @@ -0,0 +1,63 @@ + +
    +
    + Thank you! +
    +
    + We successfully received your order. An Email has been sent to you containing all the order details. +
    +
    +
    +

    + Confirmation +

    +
    +
    +

    + Billing address +

    + +
    + +
    +

    + Shipment +

    + +
    + +

    + Title + 1 +

    + +
    +
    +
    + +
    +

    + Payment +

    + +

    + Title +

    + +
    +
    + + +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/confirmation.py b/src/pcommerce/core/browser/components/confirmation.py new file mode 100644 index 0000000..5cdafbb --- /dev/null +++ b/src/pcommerce/core/browser/components/confirmation.py @@ -0,0 +1,16 @@ +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.browser.components.base import BaseComponent + +class ConfirmationComponent(BaseComponent): + index = ViewPageTemplateFile('confirmation.pt') + + def validate(self): + return True + + def process(self): + return + + @property + def address(self): + return self.order.address diff --git a/src/pcommerce/core/browser/components/gtc.pt b/src/pcommerce/core/browser/components/gtc.pt new file mode 100644 index 0000000..243d98a --- /dev/null +++ b/src/pcommerce/core/browser/components/gtc.pt @@ -0,0 +1,28 @@ + +
    +
    +
    + The Error +
    + + + (Required) + +
    +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/gtc.py b/src/pcommerce/core/browser/components/gtc.py new file mode 100644 index 0000000..11b1d62 --- /dev/null +++ b/src/pcommerce/core/browser/components/gtc.py @@ -0,0 +1,27 @@ +from zope.component import getMultiAdapter +from plone.memoize.instance import memoize + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.CMFCore.utils import getToolByName + +from pcommerce.core.browser.components.base import BaseComponent +from pcommerce.core import PCommerceMessageFactory as _ + +class GTCComponent(BaseComponent): + index = ViewPageTemplateFile('gtc.pt') + + def validate(self): + self.errors = {} + if self.request.form.get('gtc'): + return True + self.errors['gtc'] = _('The general terms and conditions have to be accepted to finish your check out.') + return False + + def process(self): + return + + @memoize + def gtc(self): + props = getToolByName(self.context, 'portal_properties').pcommerce_properties + portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') + return '%s/%s' % (portal_state.portal_url(), props.getProperty('gtc', '')) diff --git a/src/pcommerce/core/browser/components/overview.pt b/src/pcommerce/core/browser/components/overview.pt new file mode 100644 index 0000000..b197c5c --- /dev/null +++ b/src/pcommerce/core/browser/components/overview.pt @@ -0,0 +1,55 @@ + +
    +

    + Overview +

    +
    +
    +

    + Billing address +

    + +
    + +
    +

    + Shipment +

    + +
    + +

    + Title + 1 +

    + +
    +
    +
    + +
    +

    + Payment +

    + +

    + Title +

    + +
    +
    + + +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/overview.py b/src/pcommerce/core/browser/components/overview.py new file mode 100644 index 0000000..eade921 --- /dev/null +++ b/src/pcommerce/core/browser/components/overview.py @@ -0,0 +1,16 @@ +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.browser.components.base import BaseComponent + +class OverviewComponent(BaseComponent): + index = ViewPageTemplateFile('overview.pt') + + def validate(self): + return True + + def process(self): + return + + @property + def address(self): + return self.order.address diff --git a/src/pcommerce/core/browser/components/payment.pt b/src/pcommerce/core/browser/components/payment.pt new file mode 100644 index 0000000..f61507d --- /dev/null +++ b/src/pcommerce/core/browser/components/payment.pt @@ -0,0 +1,17 @@ + +
    +

    + Payment +

    + + +
    + diff --git a/src/pcommerce/core/browser/components/payment.py b/src/pcommerce/core/browser/components/payment.py new file mode 100644 index 0000000..6d5ae83 --- /dev/null +++ b/src/pcommerce/core/browser/components/payment.py @@ -0,0 +1,27 @@ +from zope.component import queryMultiAdapter + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.interfaces import IPaymentView +from pcommerce.core.browser.components.base import BaseComponent + +class PaymentComponent(BaseComponent): + index = ViewPageTemplateFile('payment.pt') + + dependencies = ('payments',) + + def validate(self): + return self.paymentview and self.paymentview.validate() + + def process(self): + if self.paymentview: + self.order.paymentdata = self.paymentview.process() + + def renders(self): + if self.paymentview and self.paymentview.renders(): + return True + if len(self._payments()) == 1: + paymentview = queryMultiAdapter((self._payments().values()[0], self.request), name=self.__name__, interface=IPaymentView) + if paymentview is not None: + return paymentview.__of__(self.context).renders() + return False \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/payments.pt b/src/pcommerce/core/browser/components/payments.pt new file mode 100644 index 0000000..bbe166f --- /dev/null +++ b/src/pcommerce/core/browser/components/payments.pt @@ -0,0 +1,38 @@ + +
    +

    + Payment +

    +

    + Select the desired payment method +

    +
    +
    + The Error +
    +
      + +
    • + +
    • +
      +
    +
    +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/payments.py b/src/pcommerce/core/browser/components/payments.py new file mode 100644 index 0000000..452f65a --- /dev/null +++ b/src/pcommerce/core/browser/components/payments.py @@ -0,0 +1,29 @@ +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.browser.components.base import BaseComponent +from pcommerce.core import PCommerceMessageFactory as _ + +class PaymentsComponent(BaseComponent): + index = ViewPageTemplateFile('payments.pt') + error = None + + def validate(self): + self.error = None + if len(self._payments()) == 1: + return True + id = self.request.form.get('payment_id') + if id is not None and self._payments().has_key(id): + return True + self.error = _(u'Please select a payment method.') + return False + + def process(self): + id = self.request.form.get('payment_id', len(self._payments()) == 1 and self.payments[0]['id']) + self.order.paymentid = id + if self.order.paymentdata and not self.order.paymentdata.id == id: + self.order.paymentdata = None + + def renders(self): + if len(self._payments())>1: + return True + return False diff --git a/src/pcommerce/core/browser/components/shipment.pt b/src/pcommerce/core/browser/components/shipment.pt new file mode 100644 index 0000000..bf55915 --- /dev/null +++ b/src/pcommerce/core/browser/components/shipment.pt @@ -0,0 +1,26 @@ + +
    +

    + Shipment +

    + +
    +

    + Title +

    + + +
    +
    +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/shipment.py b/src/pcommerce/core/browser/components/shipment.py new file mode 100644 index 0000000..130b418 --- /dev/null +++ b/src/pcommerce/core/browser/components/shipment.py @@ -0,0 +1,50 @@ +from persistent.mapping import PersistentMapping + +from zope.component import queryMultiAdapter + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.interfaces import IShipmentView +from pcommerce.core.browser.components.base import BaseComponent + +class ShipmentComponent(BaseComponent): + index = ViewPageTemplateFile('shipment.pt') + + dependencies = ('shipments',) + + def validate(self): + valid = True + for shipment in self.shipments: + if shipment['view'] is not None: + if not shipment['view'].validate(): + valid = False + return valid + + def process(self): + self.order.shipmentdata = PersistentMapping() + for shipment in self.shipments: + if shipment['view'] is not None: + shipmentdata = shipment['view'].process() + self.order.shipmentdata[shipmentdata.id] = shipmentdata + + def renders(self): + for shipment in self.shipments: + if shipment['renders']: + return True + for shipmentids in self._shipmentgroups().keys(): + if not len(shipmentids) == 1: + continue + shipmentview = queryMultiAdapter((self._shipments()[shipmentids[0]], self.request), name=self.__name__, interface=IShipmentView) + if shipmentview is not None: + if shipmentview.__of__(self.context).renders(): + return True + return False + + @property + def multiple(self): + count = 0 + for shipment in self.shipments: + if shipment['renders']: + count += 1 + return count > 1 + diff --git a/src/pcommerce/core/browser/components/shipments.pt b/src/pcommerce/core/browser/components/shipments.pt new file mode 100644 index 0000000..995f77a --- /dev/null +++ b/src/pcommerce/core/browser/components/shipments.pt @@ -0,0 +1,89 @@ + +
    +

    + Shipment +

    + +

    + Select the desired shipment method +

    + +
    +
    + The Error +
    + + + +
      + +
    • + +
    • +
      +
    +
    +
    +
    + + + +
    +

    + Select the desired shipment method for the following products: +

    +
      +
    • + + +
    • +
    +
    + The Error +
    +
      + +
    • + +
    • +
      +
    +
    +
    +
    +
    + \ No newline at end of file diff --git a/src/pcommerce/core/browser/components/shipments.py b/src/pcommerce/core/browser/components/shipments.py new file mode 100644 index 0000000..62b495b --- /dev/null +++ b/src/pcommerce/core/browser/components/shipments.py @@ -0,0 +1,63 @@ +from persistent.mapping import PersistentMapping + +from plone.memoize.instance import memoize + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.browser.components.base import BaseComponent +from pcommerce.core import PCommerceMessageFactory as _ + +class ShipmentsComponent(BaseComponent): + index = ViewPageTemplateFile('shipments.pt') + + @property + @memoize + def selection(self): + return dict([(value['products'], value['shipmentid']) for key, value in self.request.form.items() if key.startswith('shipment_id_') and value.has_key('shipmentid')]) + + def validate(self): + self.errors = {} + valid = True + for shipmentids, products in self._shipmentgroups().items(): + if len(shipmentids) > 1: + key = tuple([p.UID() for p in products]) + if not self.selection.has_key(key): + self.errors[shipmentids] = _(u'Please select a shipment method.') + valid = False + elif not self.selection[key] in shipmentids: + self.errors[shipmentids] = _(u'Please select a shipment method.') + valid = False + return valid + + def process(self): + self.order.shipmentids = PersistentMapping() + for shipmentids, products in self._shipmentgroups().items(): + key = tuple([p.UID() for p in products]) + if len(shipmentids) > 1: + shipmentid = self.selection[key] + else: + shipmentid = shipmentids[0] + if not self.order.shipmentids.has_key(shipmentid): + self.order.shipmentids[shipmentid] = () + self.order.shipmentids[shipmentid] = self.order.shipmentids[shipmentid] + key + + def renders(self): + if len(self._shipments())==1: + return False + for shipments in self._shipmentgroups().keys(): + if len(shipments)>1: + return True + return False + + @property + def multiple(self): + shipmentsgroups = self._shipmentgroups() + if len(shipmentsgroups) == 1: + return False + count = 0 + for shipments in shipmentsgroups.keys(): + if len(shipments) > 1: + count = count+1 + if count > 1: + return True + return False diff --git a/src/pcommerce/core/browser/configlet.pt b/src/pcommerce/core/browser/configlet.pt new file mode 100644 index 0000000..e171474 --- /dev/null +++ b/src/pcommerce/core/browser/configlet.pt @@ -0,0 +1,276 @@ + + + + +
    + +

    + PCommerce configuration +

    + + + Up to Site Setup + + +
    + +
    + + + + + (Required) + + +
    + The name appearing in payment-terminals +
    + +
    + The Error +
    + +
    + +
    +
    + +
    + + + +
    + The path to the page holding the general terms and conditions to accept before payment +
    + +
    + The Error +
    + +
    + +
    +
    + +
    + + + +
    + The path to the page to be redirected to after checkout +
    + +
    + The Error +
    + +
    + +
    +
    + +
    + + + +
    + The email address receiving and sending pcommerce related emails +
    + +
    + The Error +
    + +
    + +
    +
    + +
    + +
    + +
    + + + +
    + Should the order process avaible for non Plone Portal Member +
    + +
    + The Error +
    + +
    + +
    + Taxes + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ZoneTax nameTax factor
    + + + + + + + + + + + The Error + +
    + + + + + + + + + + The Error + +
    +
    + +
    + Tax included in product price + + + + + + + + + + + + + + + +
    Tax nameTax factor
    + + + + + + The Error + +
    +
    + +
    + + + +
    + +
    + +
    + + + + diff --git a/src/pcommerce/core/browser/configlet.py b/src/pcommerce/core/browser/configlet.py new file mode 100644 index 0000000..008a2cb --- /dev/null +++ b/src/pcommerce/core/browser/configlet.py @@ -0,0 +1,92 @@ +from plone.memoize.instance import memoize + +from Products.statusmessages.interfaces import IStatusMessage +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone import PloneMessageFactory as _p + +from pcommerce.core.interfaces import ITaxes +from pcommerce.core import PCommerceMessageFactory as _ + +class PCommerceConfiglet(BrowserView): + """PCommerce configlet + """ + + template = ViewPageTemplateFile('configlet.pt') + properties = ('productname','gtc','post_checkout','email_address','noregistration_order') + values = {} + + def __call__(self): + self.request.set('disable_border', True) + self.errors = {} + + props = getToolByName(self.context, 'portal_properties').pcommerce_properties + if self.request.form.has_key('pcommerce_save'): + adapter = ITaxes(self.context) + taxes = [] + raw = self.request.form.get('taxes', []) + for tax in raw: + if not tax.has_key('remove') or not tax['remove']: + try: + tax = {'id': tax['id'], + 'tax': float(tax['tax']), + 'zone': tax['zone'], + 'taxname': tax['taxname']} + if tax['zone'] == '': + self.errors[tax['id']] = _(u'Please provide a zone name') + elif tax['taxname'] == '': + self.errors[tax['id']] = _(u'Please provide a tax name') + if not self.errors.has_key(tax['id']): + taxes.append(tax) + except: + self.errors[tax['id']] = _(u'Please enter a floating point number (e.g. 7.6)') + for prop in self.properties: + self.values[prop] = self.request.form.get(prop, '') + + + taxincl = None + tax = self.request.form.get('taxincl.tax', '') + taxname = self.request.form.get('taxincl.taxname', '') + + try: + if taxname == '' and tax != '': + self.errors['taxincl'] = _(u'Please provide a tax name') + else: + if tax == '': + tax = 0.0 + taxincl = (float(tax), taxname) + except: + self.errors['taxincl'] = _(u'Please enter a floating point number (e.g. 7.6)') + + if not self.errors: + adapter.edit(taxes) + adapter.taxincl = taxincl + IStatusMessage(self.request).addStatusMessage(_p('Properties saved'), 'info') + for prop in self.properties: + if prop == 'columns': + self.values[prop] = int(self.values[prop]) + props._setPropValue(prop, self.values[prop]) + else: + IStatusMessage(self.request).addStatusMessage(_p(u'Please correct the indicated errors'), 'error') + + for prop in self.properties: + self.values[prop] = props.getProperty(prop, '') + + return self.template() + + @property + @memoize + def taxes(self): + utils = getToolByName(self.context, 'plone_utils') + taxes = ITaxes(self.context) + return [{'id': utils.normalizeString(zone), + 'zone': zone, + 'tax': tax[0], + 'taxname': tax[1]} for zone, tax in taxes.items()] + + @property + def taxincl(self): + taxes = ITaxes(self.context) + return {'tax': taxes.taxincl[0], + 'taxname': taxes.taxincl[1]} diff --git a/src/pcommerce/core/browser/configure.zcml b/src/pcommerce/core/browser/configure.zcml new file mode 100644 index 0000000..701e734 --- /dev/null +++ b/src/pcommerce/core/browser/configure.zcml @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/browser/folder.pt b/src/pcommerce/core/browser/folder.pt new file mode 100644 index 0000000..d75a24a --- /dev/null +++ b/src/pcommerce/core/browser/folder.pt @@ -0,0 +1,51 @@ + + + + + + +
    + +
    + +

    + Title +

    + +
    + +
    + Description +
    + +
    + +
    + Portal status message +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/folder.py b/src/pcommerce/core/browser/folder.py new file mode 100644 index 0000000..4a2649d --- /dev/null +++ b/src/pcommerce/core/browser/folder.py @@ -0,0 +1,92 @@ +from Acquisition import aq_inner, aq_parent + +from zope.interface import implements + +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from Products.CMFCore.utils import getToolByName +from Products.ATContentTypes.interface.image import IImageContent + +from plone.memoize.instance import memoize +from plone.app.content import browser +from plone.app.content.batching import Batch + +from pcommerce.core.interfaces import IPricing, IShopFolder, IShop, IProduct +from pcommerce.core.currency import CurrencyAware + +batching_path = '/'.join(browser.__path__) + +class ShopHome(BrowserView): + """ shop home view + """ + implements(IShop) + + template = ViewPageTemplateFile('folder.pt') + + def __call__(self): + return self.template() + +class ShopFolderListing(BrowserView): + """ shop folder listing + """ + implements(IShopFolder) + + template = ViewPageTemplateFile('folder.pt') + batching = ViewPageTemplateFile('%s/batching.pt' % batching_path) + + def __call__(self): + self.page = int(self.request.get('pagenumber', 1)) + self.url = self.context.absolute_url() + return self.template() + + @property + @memoize + def batch(self): + catalog = getToolByName(self.context, 'portal_catalog') + portal_properties = getToolByName(self.context, 'portal_properties') + use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) + props = portal_properties.pcommerce_properties + columns = int(props.getProperty('columns', 3)) + width = int(props.getProperty('thumb_width', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + results = catalog(object_provides=IProduct.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), 'depth': 1}, sort_on='getObjPositionInParent') + items = [] + i = 0 + start = (self.page-1) * (columns * 5) + end = start + columns * 5 + for item in results: + url = item.getURL() + if item.portal_type in use_view_action: + url += '/view' + + if start <= i < end: + object = item.getObject() + col = i % columns + 1 + adapter = IPricing(object) + image = None + if object.getImage(): + image = {'caption': object.getImageCaption(), + 'thumb': '%s/%s' % (item.getURL(), width)} + + item = {'uid': item.UID, + 'class': 'col%s' % col, + 'title': item.Title, + 'description': item.Description, + 'price': CurrencyAware(adapter.getPrice()), + 'base_price': CurrencyAware(adapter.getBasePrice()), + 'offer': adapter.getPrice() < adapter.getBasePrice(), + 'image': image, + 'url': url} + else: + item = {'uid': item.UID, + 'title': item.Title, + 'description': item.Description, + 'url': url} + i += 1 + items.append(item) + return Batch(items, columns * 5, self.page, 5) + + @property + @memoize + def multiple_pages(self): + return self.batch.size > self.batch.pagesize diff --git a/src/pcommerce/core/browser/getprice.js b/src/pcommerce/core/browser/getprice.js new file mode 100644 index 0000000..e0debb8 --- /dev/null +++ b/src/pcommerce/core/browser/getprice.js @@ -0,0 +1,27 @@ +/* + * PCommerce GetPrice + */ +jq('document').ready(function() { + + jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { + jq(this).find('option').each(function(i) { + html = jq(this).html(); + jq(this).html(html.substring(0, html.lastIndexOf('('))); + }); + }); + + if (jq('.buyViewlet select[name="cartVariation:list"]').length) { + pcommerceLoadPrice(); + } + jq('.buyViewlet select[name="cartVariation:list"]').change(function(){ + pcommerceLoadPrice(); + }); +}); + +function pcommerceLoadPrice(){ + var variations = []; + jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { + variations[i] = jq(this).attr('value'); + }); + jq('.portletInfoBox .priceInfo').load('getprice?v='+variations.join(',')); +} diff --git a/src/pcommerce/core/browser/getprice.pt b/src/pcommerce/core/browser/getprice.pt new file mode 100644 index 0000000..0aa3720 --- /dev/null +++ b/src/pcommerce/core/browser/getprice.pt @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/getprice.py b/src/pcommerce/core/browser/getprice.py new file mode 100644 index 0000000..9b7929b --- /dev/null +++ b/src/pcommerce/core/browser/getprice.py @@ -0,0 +1,40 @@ +from Acquisition import aq_parent, aq_inner + +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from Products.CMFCore.utils import getToolByName + +from pcommerce.core.interfaces import IPricing, IProduct, IVariation +from pcommerce.core.currency import CurrencyAware + +class GetPrcie(BrowserView): + """ A AJAX interface for getPrece of the product + """ + + template = ViewPageTemplateFile('getprice.pt') + + def __call__(self): + return self.template() + + def price(self): + import logging + v_uid = None + product = aq_inner(self.context) + if IVariation.providedBy(product): + product = aq_parent(product) + v_uid = self.context.UID() + + v_uids = self.request.get('v', '') + v_uids = v_uids.split(',') + v_uids = [uid for uid in v_uids if uid != ''] + if not len(v_uids) and v_uid is not None: + v_uids = [v_uid,] + + catalog = getToolByName(self.context, 'uid_catalog') + variations = catalog(object_provides=IVariation.__identifier__, UID=v_uids) + variations = [variation.getObject() for variation in variations] + + price = IPricing(product).getPrice(variations) + + return CurrencyAware(price) \ No newline at end of file diff --git a/src/pcommerce/core/browser/images.pt b/src/pcommerce/core/browser/images.pt new file mode 100644 index 0000000..dab07c3 --- /dev/null +++ b/src/pcommerce/core/browser/images.pt @@ -0,0 +1,132 @@ + + + + + + + + + +
    + + + Add image + + +

    + Images +

    + +
    +
    Info
    +
    + You are currently looking at the images of a variation of the product + Product title. +
    +
    + +

    + This product has no images. To add an image press the + 'add' button or paste content from another location. +

    + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
      Image  Modified  
    + + + + + + + 08/19/2001 03:01 AM + + + + Edit +
    + + + + +
    + +
    +
    + + + + + + + diff --git a/src/pcommerce/core/browser/images.py b/src/pcommerce/core/browser/images.py new file mode 100644 index 0000000..d56c459 --- /dev/null +++ b/src/pcommerce/core/browser/images.py @@ -0,0 +1,52 @@ +from zope.component import getMultiAdapter +from zope.interface import implements + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from Products.CMFCore.utils import getToolByName +from Products.ATContentTypes.interface.image import IImageContent + +from plone.memoize.instance import memoize +from plone.app.content.browser.interfaces import IFolderContentsView +from plone.app.content.browser.foldercontents import FolderContentsTable + +from pcommerce.core.browser.product import Product + +class Images(Product, FolderContentsTable): + """management view of all images + """ + implements(IFolderContentsView) + + template = ViewPageTemplateFile('images.pt') + + def __call__(self): + return self.template() + + @property + @memoize + def items(self): + catalog = getToolByName(self.context, 'portal_catalog') + plone_view = getMultiAdapter((self.context, self.request), name=u'plone') + utils = getToolByName(self.context, 'plone_utils') + wftool = getToolByName(self.context, 'portal_workflow') + results = catalog(object_provides=IImageContent.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), + 'depth': 1}) + images = [] + odd = True + for image in results: + images.append({'uid': image.UID, + 'id': image.getId, + 'modified': plone_view.toLocalizedTime(image.ModificationDate, long_format=1), + 'state_title': wftool.getTitleForStateOnType(image.review_state, image.portal_type), + 'state_class': 'state-' + utils.normalizeString(image.review_state), + 'is_expired': self.context.isExpired(image), + 'title_or_id': image.pretty_title_or_id(), + 'table_row_class': odd and 'odd' or 'even', + 'path': image.getPath, + 'relative_url': image.getURL(relative=True), + 'image_thumb': '%s/image_thumb' % image.getURL(), + 'url': {'edit': '%s/edit' % image.getURL(), + 'sharing': '%s/@@sharing' % image.getURL()}}) + """Thumb with height width parameters... ??? """ + odd = not odd + return images diff --git a/src/pcommerce/core/browser/images/price_icon.gif b/src/pcommerce/core/browser/images/price_icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..3013b1a48fe02deacc15f41c5e405c9a590964f3 GIT binary patch literal 595 zcmV-Z0<8T60c(C27U7=a{{P*AP z-N@&}rP-f*wsw}vk*v+Du-&Vo*PNKklaj}csM?}^xp|MoiLK77jl+ny;<9C|V6xt< zXRc$a+@oo#WsJjzhrxn}!h(gtfNG~_W~X6`!iIvpe%brOKmXqh5r)fPcAq(d5vExPx-KZCamJ#N@%woV(t)nZlQ++M%1xmWRKCd$)I@*qf5ZjFH5PT%cH~+oQ?lb`k)MgH2Ky9RY4blqE7Kacy;AA0CK!EGl{; zQv?imE;WQ}4pb)z1xgGX0|GOf6)?y%EKvTIqygv9YYm4i`hx4Y~tdbrf?EUj~SDGCFb zEShse3OYkTY#cX+j0xPpu?@B{$J{Z-9+-T;?D@NA`0jzhKAnF?@4w*n%e&%OIpOeE zI0y&DWDr=L--sgX_CXMox-`weJBq1JZ^jX@Y6!?1oWn}|{+jbbZ?<0y!#-3Bb84_^!V-h05&s!8xY?2E` z0Try7UHY45F*T&UfuZ`P(bIn0L@Mb5R#pg}nr_YkaEC{9#3Ujo&A&TG&cb~}M10OR z-k37|=8+J?QffQ`JLWiEc}dd3@lRj(O3R(1V)rBo)77OG=pdr?DH=k^Xk>x6(w`6f z6JY~;;o*s8e_End`ZQ38T;lc-9~&9kd`OJkRe17|&wGO%(-bu$;NX(CI4 zn6V}JRAGPcGqCrDbgZO*7GNd-0Q5gBJFztlf@ILaXZB}LKp7Zx{e{;bHe_zwzUAfp z-17+TS`~fw&X4ypE8eIXFa9E1xG(!H0%fBU+5N*FK`v>3&rk1b7zgtXQ1R_krHy@W zU)W1fQcg5w;X7=EYuqB%VEWaQn^UzeZ5otbxFh?+W6<-jl@jH&yG5mc?#h@ri68vF ze0yabgPs1-Ecq&>jPgsktDDzZD6S`edFvfA1T}L1sbR=UGHGWx^LWJlQp<@gIhSep z`;?u}?TYG1q1vrkl)ox-rHU6xZMd(m#LwWqYu}eoB^E6b57cyQs~*nabJ(xkE+4Bc hD}DkSb}(f*#H>bT)2pBV%Fgudak1WHrlmmz{{i~&8*%^u literal 0 HcmV?d00001 diff --git a/src/pcommerce/core/browser/images/variation_icon.gif b/src/pcommerce/core/browser/images/variation_icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a1291a7448f1fa25eec9f4eb160e55d4c80f334 GIT binary patch literal 1048 zcmdVZ{ZrC+0KoAt%a-kS<UK7`>Bv>S&mB?39o{RPIh)s(`6H$^N4VIs%UIQFA#!gce@a+-NJ}`D0#o!9K~5{<0%7*_ethgxvAZ%Wzw znUYrF*U^mw6&60;B_Sea&ba7XhxqK6Am7F(sIFmN#$R}zl<1hXmf?Ecz1nH>(U^e( z79Ro|6-2Fw`Q9S0Ffer~g6K?xc#n#roomo@FsbJZr?fTYxF)CWh9?=ek;26Xl`u@T z@T!-eOM?a)@{|}57WB{L2cP1Te$~R*0hn8vK%T{;ROJ7i8K@hNuXV?;jf>7(jyRM z?Pl^e#)p}!GPhF~RPSs!*_*Xa-A7~p&u?Oijq8t9LWzy18Yj?uE|4&7 zXzc2>TZ&q<61+7fci*`4Bc + + + CHF 150.00 + instead of + CHF 200.00 + + + CHF 200.00 + + + + + + + + + Title + + 1 + + + + No + +
    + +
    Type:
    +
    Name
    +
    +
    +
    + +
    +
    + + + + + Title + + + Description + +
    +
    + +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ProductAmountPricePrice total
    + + + 10 + + 50.00 + + 500.00 +
    + Total + +   + + + 500.00 + +
    + Title + 1 + +   + + + 500.00 + +
    + Total incl. charges + +   + + + 500.00 + +
    + VAT + + % + + + 500.00 + +
    + Total incl. + +   + + + 500.00 + +
    + Title + 1 + +   + + + 500.00 + +
    + Total incl. charges and + + Total incl. charges and % + + Total incl. charges + +   + + + 500.00 + +
    +
    + +
    + +

    + Title +

    +

    + Description +

    +
    + diff --git a/src/pcommerce/core/browser/manage_orders.pt b/src/pcommerce/core/browser/manage_orders.pt new file mode 100644 index 0000000..6d27ac9 --- /dev/null +++ b/src/pcommerce/core/browser/manage_orders.pt @@ -0,0 +1,59 @@ + + + + +

    Manage orders

    + + +

    No orders were found.

    +
    + + + + + + + + + + + + + + + + + +
    + + + â–² + â–¼ + +
    + + + +
    + +
    + + + + + diff --git a/src/pcommerce/core/browser/order_details.pt b/src/pcommerce/core/browser/order_details.pt new file mode 100644 index 0000000..2b27abb --- /dev/null +++ b/src/pcommerce/core/browser/order_details.pt @@ -0,0 +1,53 @@ + + + + + +

    Order details

    + + + Manage orders + + + +

    Which one?

    +

    Please supply an order id. +

    +
    + + +

    The order could not be found.

    +

    Please check the order id. +

    +
    + + +
    + +
    +
    + +
    + + + + + + diff --git a/src/pcommerce/core/browser/orders.py b/src/pcommerce/core/browser/orders.py new file mode 100644 index 0000000..34c1f66 --- /dev/null +++ b/src/pcommerce/core/browser/orders.py @@ -0,0 +1,258 @@ +import os + +from DateTime import DateTime + +from zope.i18n import translate + +from plone.app.content.batching import Batch +from plone.app.content.browser import tableview + +from Products.CMFCore.utils import getToolByName +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.currency import CurrencyAware +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.interfaces import IOrderRegistry + + +SESSION_KEY = 'pcommerce.core.manageorders.' + +class ManageOrders(BrowserView): + """Overview of all orders. + """ + + template = ViewPageTemplateFile('manage_orders.pt') + batching = ViewPageTemplateFile(os.path.join(os.path.dirname(tableview.__file__), 'batching.pt')) + + def __init__(self, *args, **kwargs): + super(ManageOrders, self).__init__(*args, **kwargs) + self.translation_service = getToolByName(self.context, + 'translation_service') + self.registry = IOrderRegistry(self.context) + self.pagesize = 20 + session = self.request.SESSION + self.pagenumber = session.get(SESSION_KEY + 'pagenumber', 1) + if self.request.get('pagenumber', None) is not None: + self.pagenumber = int(self.request.get('pagenumber')) + session.set(SESSION_KEY + 'pagenumber', self.pagenumber) + self.sort_on = session.get(SESSION_KEY + 'sort_on', 1) + self.reverse = session.get(SESSION_KEY + 'reverse', False) + if not self.request.get('sort_on', None) in ('getObjPositionInParent', '', None): + if self.request.get('sort_on', None) == self.sort_on: + self.reverse = not self.reverse + else: + self.reverse = False + self.sort_on = self.request.get('sort_on') + session.set(SESSION_KEY + 'reverse', self.reverse) + session.set(SESSION_KEY + 'sort_on', self.sort_on) + self.request.set('sort_on', '') + self.url = '%s/@@manage-orders' % self.context.absolute_url() + + def __call__(self): + self.request.set('disable_border', 1) + return self.template() + + def _translate_order_status_id(self, status_id): + """ + """ + order_status_string = { + 1: _('label_initialized', default="Initialized"), + 2: _('label_sent', default="Sent"), + 3: _('label_processed', default="Processed"), + 4: _('label_failed', default="Failed"), + 5: _('label_cancelled', default="Cancelled"), + } + return order_status_string[status_id] + + def order_fields(self): + """Fields and fieldnames to show in tables (order overviews / details). + + { 'field_id': '', + 'field_name': _("label_", default=""), + 'sortable': True + }, + """ + fields = [ + { 'field_id': 'orderid', + 'field_name': _("label_order_id", default="Order id"), + 'sortable': True + }, + { 'field_id': 'userid', + 'field_name': _("label_user_id", default="User id"), + 'sortable': True + }, + { 'field_id': 'date', + 'field_name': _("label_date", default="Date"), + 'sortable': True + }, + { 'field_id': 'currency', + 'field_name': _("label_currency", default="Currency"), + 'sortable': True + }, + { 'field_id': 'totalincl', + 'field_name': _("label_price_total", default="Price total"), + 'field_converter': self._totalincl_converter, + 'sortable': True + }, + { 'field_id': 'state', + 'field_name': _("label_order_state", default="Order status"), + 'sortable': True + }, + { 'field_id': 'zone', + 'field_name': _("label_zone", default="Zone"), + 'field_converter': self._zone_converter, + 'sortable': True + }, + { 'field_id': 'address', + 'field_name': _("label_address", default="Address"), + 'field_converter': self._address_converter, + 'sortable': True + }, + { 'field_id': 'products', + 'field_name': _("label_products", default="Products"), + 'field_converter': self._products_converter, + 'sortable': False + }, + { 'field_id': 'shipmentids', + 'field_name': _("label_shipmentids", default="Shipment id's"), + 'field_converter': self._shipmentids_converter, + 'sortable': False + }, + ] + return fields + + def _zone_converter(self, value, order): + return '%s (%s%% %s)' % (value[0], value[1][0], value[1][1]) + + def _totalincl_converter(self, value, order): + return CurrencyAware(value).valueToString() + + def _address_converter(self, value, order): + return '
    %s
    ' % value.mailInfo(self.request) + + def _products_converter(self, value, order): + rows = [] + for product in value: + cells = [str(i) for i in product[1:5]] + cells.append(str(product[3]*product[4])) + rows.append('
    - Date: Sat, 12 Jan 2013 19:13:19 +0100 Subject: [PATCH 13/27] Testing the checkout process --- buildout.cfg | 1 + setup.py | 1 + src/pcommerce/core/browser/address.pt | 6 ++-- src/pcommerce/core/browser/components/gtc.pt | 4 +-- src/pcommerce/core/browser/configlet.py | 8 ++++- src/pcommerce/core/testing.py | 6 +++- .../tests/acceptance/test_pcommerce_core.txt | 34 +++++++++++++++---- 7 files changed, 46 insertions(+), 14 deletions(-) diff --git a/buildout.cfg b/buildout.cfg index 33a2573..54bf565 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -23,6 +23,7 @@ user = admin:admin http-address = 8088 eggs = ${buildout:eggs} + collective.MockMailHost Plone Pillow plone.act diff --git a/setup.py b/setup.py index f31099c..771d950 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ extras_require = { 'test': [ 'plone.app.testing', + 'collective.MockMailHost', 'plone.act', 'Products.SingleKeywordWidget', 'pcommerce.shipment.parcel', diff --git a/src/pcommerce/core/browser/address.pt b/src/pcommerce/core/browser/address.pt index a8bc1a3..0485229 100644 --- a/src/pcommerce/core/browser/address.pt +++ b/src/pcommerce/core/browser/address.pt @@ -207,11 +207,11 @@
    - -
    @@ -345,4 +345,4 @@
    - \ No newline at end of file + diff --git a/src/pcommerce/core/browser/components/gtc.pt b/src/pcommerce/core/browser/components/gtc.pt index 243d98a..ec3d1a8 100644 --- a/src/pcommerce/core/browser/components/gtc.pt +++ b/src/pcommerce/core/browser/components/gtc.pt @@ -13,7 +13,7 @@ The Error - \ No newline at end of file + diff --git a/src/pcommerce/core/browser/configlet.py b/src/pcommerce/core/browser/configlet.py index 5a81e52..1f5b1f9 100644 --- a/src/pcommerce/core/browser/configlet.py +++ b/src/pcommerce/core/browser/configlet.py @@ -68,7 +68,13 @@ def __call__(self): if prop == 'columns': self.values[prop] = int(self.values[prop]) if prop == 'noregistration_order': - self.values[prop] = self.values[prop] == 'noregistration_order' and True or False + noreg_order = self.values[prop] == 'noregistration_order' and True or False + self.values[prop] = noreg_order + portal = getToolByName(self.context, 'portal_url').getPortalObject() + if noreg_order: + portal.manage_permission("PCommerce: Check out", roles=['Anonymous'], acquire=1) + else: + portal.manage_permission("PCommerce: Check out", roles=['Authenticated'], acquire=1) props._setPropValue(prop, self.values[prop]) else: IStatusMessage(self.request).addStatusMessage(_p(u'Please correct the indicated errors'), 'error') diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py index 1581080..3223849 100644 --- a/src/pcommerce/core/testing.py +++ b/src/pcommerce/core/testing.py @@ -29,15 +29,18 @@ def setUpZope(self, app, configurationContext): import Products.SingleKeywordWidget import pcommerce.shipment.parcel import pcommerce.payment.invoice + import collective.MockMailHost self.loadZCML(package=pcommerce.core) self.loadZCML(package=pcommerce.shipment.parcel) self.loadZCML(package=pcommerce.payment.invoice) self.loadZCML(package=Products.SingleKeywordWidget) + self.loadZCML(package=collective.MockMailHost) # Install product and call its initialize() function z2.installProduct(app, 'pcommerce.core') z2.installProduct(app, 'pcommerce.shipment.parcel') z2.installProduct(app, 'pcommerce.shipment.invoice') + z2.installProduct(app, 'collective.MockMailHost') # Note: you can skip this if my.product is not a Zope 2-style # product, i.e. it is not in the Products.* namespace and it @@ -59,13 +62,14 @@ def setUpPloneSite(self, portal): quickInstallProduct(portal, 'pcommerce.core') quickInstallProduct(portal, 'pcommerce.shipment.parcel') quickInstallProduct(portal, 'pcommerce.shipment.invoice') + quickInstallProduct(portal, 'collective.MockMailHost') def tearDownZope(self, app): # Uninstall product z2.uninstallProduct(app, 'pcommerce.core') z2.uninstallProduct(app, 'pcommerce.shipment.parcel') z2.uninstallProduct(app, 'pcommerce.shipment.invoice') - + z2.uninstallProduct(app, 'collective.MockMailHost') PCOMMERCE_TDD_FIXTURE = pcommerceCoreTddLayer() diff --git a/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt index 1821b6f..ea892d1 100644 --- a/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt +++ b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt @@ -29,6 +29,20 @@ Create Product Input text title ${title} Click Button Save +Go through checkout + Go to ${front-page}/my-product + Click Button add to cart + Go to ${front-page}/@@cart + Click Button Check out + Input text firstname My firstname + Input text lastname My lastname + Input text address1 My address1 + Input text zip 000000 + Input text city My city + Input text country My country + Input text email email@email.com + Input text phone 000000 0000 + *** Test Cases *** Test Noregistration switch visible @@ -65,8 +79,7 @@ Test No Registration needed Page should not contain You have to be registered to check out your order, -Test Go trough checkout - Set Selenium Speed 0.5 seconds +Test Go through checkout as anonymous Log in as site owner Create Product My product Page should contain Changes saved. @@ -75,8 +88,15 @@ Test Go trough checkout Click Button Save Page should contain Properties saved Log out - Go to ${front-page}/my-product - Click Button add to cart - Go to ${front-page}/@@cart - Click Button Check out - Input text firstname My firstname + Go through checkout + Click Button Next step + Page should contain equal to billing address + Click Button Next step + Page should contain equal to customer address + Click Button Next step + Page should contain Overview + Click Element id=gtc_box + Click Button Send order + Page should contain We successfully received your order. + + From 300d6f0d00af7734e8155a50fe6584f87d0d1020 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Sat, 12 Jan 2013 19:59:31 +0100 Subject: [PATCH 14/27] Test cleanup --- src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt index ea892d1..aade4b2 100644 --- a/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt +++ b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt @@ -55,7 +55,6 @@ Test Registration needed Log in as site owner Create Product My product Page should contain Changes saved. - #Workflow Publish Log out Go to ${front-page}/my-product Click Button add to cart From 587f0c30e56b1ead69be03a738db87d1ce346be9 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Mon, 14 Jan 2013 15:01:47 +0100 Subject: [PATCH 15/27] Update docs/TODO.txt Order without registration possible --- docs/TODO.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index fd473af..8eec2e4 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -8,15 +8,15 @@ Customers Membership integration ~~~~~~~~~~~~~~~~~~~~~~ -Integrate order form with site membership, or don't require membership? +[x] Integrate order form with site membership, or don't require membership? Switch in control panel -The payment process should be easier for customers, now lots of duplicate +[] The payment process should be easier for customers, now lots of duplicate data have to be filled in. Product filtering ~~~~~~~~~~~~~~~~~ -Filter on product properties to narrow down products (ajax?) +[] Filter on product properties to narrow down products (ajax?) Vendor @@ -25,11 +25,11 @@ Vendor Order management ~~~~~~~~~~~~~~~~ -* batching (implemented in 1.0b12) +[x] batching (implemented in 1.0b12) -* filtering (on status, for example) +[] filtering (on status, for example) -* Integrate processing here? The current way is rather flimsy: vendor clicks a +[] Integrate processing here? The current way is rather flimsy: vendor clicks a link from an email which takes him to the processOrder page, which redirects to a blank page displaying only "order processed". @@ -40,6 +40,6 @@ Order management General ------- -* Layout: currently has own CSS looking like Plone 3. Try styling by adding +[] Layout: currently has own CSS looking like Plone 3. Try styling by adding only classes, so we use Plone's own styling (should work in both 3 and 4). -* Translations: replace bare strings with labels and defaults +[] Translations: replace bare strings with labels and defaults From 215d6ea129459dc5dcef09eb2f47cd63aef3ed72 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Tue, 15 Jan 2013 10:15:06 +0100 Subject: [PATCH 16/27] Update README.rst Travis url fixed --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 234c24a..76976c7 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ Introduction PCommerce (Plone commerce) provides a simple shop system which supports: .. image:: https://api.travis-ci.org/Gomez/pcommerce.core.png - :target: http://travis-ci.org/Gomez/pcommerce.core.png + :target: https://travis-ci.org/Gomez/pcommerce.core * product variations * multiple prices per product to support special prices per user or group From 887f65e2b4fe71ee3a94449bff078236c1b30934 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Wed, 3 Jul 2013 09:48:51 +0200 Subject: [PATCH 17/27] jq is deprecated - replaced with $ --- src/pcommerce/core/browser/getprice.js | 20 +++++++++---------- .../core/browser/javascripts/as_customer.js | 14 ++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/pcommerce/core/browser/getprice.js b/src/pcommerce/core/browser/getprice.js index e0debb8..076c36a 100644 --- a/src/pcommerce/core/browser/getprice.js +++ b/src/pcommerce/core/browser/getprice.js @@ -1,27 +1,27 @@ /* * PCommerce GetPrice */ -jq('document').ready(function() { +$('document').ready(function() { - jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { - jq(this).find('option').each(function(i) { - html = jq(this).html(); - jq(this).html(html.substring(0, html.lastIndexOf('('))); + $('.buyViewlet select[name="cartVariation:list"]').each(function(i) { + $(this).find('option').each(function(i) { + html = $(this).html(); + $(this).html(html.substring(0, html.lastIndexOf('('))); }); }); - if (jq('.buyViewlet select[name="cartVariation:list"]').length) { + if ($('.buyViewlet select[name="cartVariation:list"]').length) { pcommerceLoadPrice(); } - jq('.buyViewlet select[name="cartVariation:list"]').change(function(){ + $('.buyViewlet select[name="cartVariation:list"]').change(function(){ pcommerceLoadPrice(); }); }); function pcommerceLoadPrice(){ var variations = []; - jq('.buyViewlet select[name="cartVariation:list"]').each(function(i) { - variations[i] = jq(this).attr('value'); + $('.buyViewlet select[name="cartVariation:list"]').each(function(i) { + variations[i] = $(this).attr('value'); }); - jq('.portletInfoBox .priceInfo').load('getprice?v='+variations.join(',')); + $('.portletInfoBox .priceInfo').load('getprice?v='+variations.join(',')); } diff --git a/src/pcommerce/core/browser/javascripts/as_customer.js b/src/pcommerce/core/browser/javascripts/as_customer.js index 82216cb..4b1db58 100644 --- a/src/pcommerce/core/browser/javascripts/as_customer.js +++ b/src/pcommerce/core/browser/javascripts/as_customer.js @@ -1,12 +1,12 @@ -jq('document').ready(function() { - var parents = jq('#checkout .component:has(.as_customer)'); +$('document').ready(function() { + var parents = $('#checkout .component:has(.as_customer)'); parents.each(function() { - if(jq(this).find('.as_customer').is(':checked')) - jq(this).find('.address').hide(); + if($(this).find('.as_customer').is(':checked')) + $(this).find('.address').hide(); }); parents.find('.as_customer').click(function() { - var checkbox = jq(this); - var parent = jq(this); + var checkbox = $(this); + var parent = $(this); while(!parent.find('.address').size()) parent = parent.parent(); if ( checkbox.is(':checked') ) @@ -14,4 +14,4 @@ jq('document').ready(function() { else parent.find('.address').show(); }); -}); \ No newline at end of file +}); From 7474cb67b55b0981110f91e6c589a8f2033ba4bb Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Wed, 3 Jul 2013 12:01:26 +0200 Subject: [PATCH 18/27] Different API - plone.batching --- src/pcommerce/core/browser/folder.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pcommerce/core/browser/folder.py b/src/pcommerce/core/browser/folder.py index 5e0c1d4..5cab7b6 100644 --- a/src/pcommerce/core/browser/folder.py +++ b/src/pcommerce/core/browser/folder.py @@ -16,12 +16,14 @@ from plone import batching batching_path = "/".join(batching.__path__) batchingfile = '%s/batchnavigation.pt' % batching_path + HAS_PLONE43 = True except: # Plone <= 4.2 from plone.app.content import browser from plone.app.content.batching import Batch batching_path = '/'.join(browser.__path__) batchingfile = '%s/batching.pt' % batching_path + HAS_PLONE43 = False from pcommerce.core.interfaces import IPricing, IShopFolder, IShop, IProduct from pcommerce.core.currency import CurrencyAware @@ -95,8 +97,13 @@ def batch(self): 'url': url} i += 1 items.append(item) - return Batch(items, columns * 5, self.page, 5) - + #different API - plone.batching + #http://stackoverflow.com/questions/16165446/from-plone-app-content-batching-import-batch-fails-with-importerror-no-module-n + if HAS_PLONE43: + return Batch(items, size=columns * 5, start=0, end=0, orphan=0, overlap=0, pagerange=7) + else: + return Batch(items, pagesize=columns * 5, pagenumber=self.page, navlistsize=5) + @property @memoize def multiple_pages(self): From 9fe809ab9a56e10d37ebe320fff97a0624ed3a39 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Wed, 3 Jul 2013 12:25:27 +0200 Subject: [PATCH 19/27] collective.MockMailHost in src - pypi rls not working --- buildout.cfg | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buildout.cfg b/buildout.cfg index 54bf565..e30878f 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -47,6 +47,8 @@ defaults = ['--auto-color', '--auto-progress'] [sources] plone.act = git git://github.com/plone/plone.act.git +#Bad release 0.6 on PyPi - delete if its fixed +collective.MockMailHost = https://github.com/collective/collective.mockmailhost.git [versions] pcommerce.payment.invoice = 1.0b5 From 82d5c21446375b18256f5a637b504412fed628f3 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Wed, 3 Jul 2013 14:27:49 +0200 Subject: [PATCH 20/27] Correct src checkout --- buildout.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildout.cfg b/buildout.cfg index e30878f..9473dfc 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -48,7 +48,7 @@ defaults = ['--auto-color', '--auto-progress'] [sources] plone.act = git git://github.com/plone/plone.act.git #Bad release 0.6 on PyPi - delete if its fixed -collective.MockMailHost = https://github.com/collective/collective.mockmailhost.git +collective.MockMailHost = git https://github.com/collective/collective.mockmailhost.git [versions] pcommerce.payment.invoice = 1.0b5 From 79f25e53aeb5b445a9d7ae819be377d39410f278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=A4ser?= Date: Wed, 25 Sep 2013 09:51:44 +0200 Subject: [PATCH 21/27] No longer use the deprecated jq alias in JavaScript --- .../core/browser/javascripts/as_customer.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pcommerce/core/browser/javascripts/as_customer.js b/src/pcommerce/core/browser/javascripts/as_customer.js index 4b1db58..645164f 100644 --- a/src/pcommerce/core/browser/javascripts/as_customer.js +++ b/src/pcommerce/core/browser/javascripts/as_customer.js @@ -1,4 +1,9 @@ +<<<<<<< HEAD:src/pcommerce/core/browser/javascripts/as_customer.js $('document').ready(function() { +======= +(function($) { + $('document').ready(function() { +>>>>>>> No longer use the deprecated jq alias in JavaScript:pcommerce/core/browser/javascripts/as_customer.js var parents = $('#checkout .component:has(.as_customer)'); parents.each(function() { if($(this).find('.as_customer').is(':checked')) @@ -9,9 +14,14 @@ $('document').ready(function() { var parent = $(this); while(!parent.find('.address').size()) parent = parent.parent(); - if ( checkbox.is(':checked') ) + if(checkbox.is(':checked') ) parent.find('.address').hide(); else parent.find('.address').show(); }); +<<<<<<< HEAD:src/pcommerce/core/browser/javascripts/as_customer.js }); +======= + }); +})(jQuery); +>>>>>>> No longer use the deprecated jq alias in JavaScript:pcommerce/core/browser/javascripts/as_customer.js From 7005bb56e85d175db77695a6fe44fe1d21421d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=A4ser?= Date: Wed, 25 Sep 2013 09:52:33 +0200 Subject: [PATCH 22/27] Fixed AttributeError in related products viewlet and improved viewlets to explicitly get the product view rather than assuming they are rendered on it --- docs/HISTORY.txt | 5 ++++- src/pcommerce/core/browser/viewlets/buy.py | 15 ++++++------- src/pcommerce/core/browser/viewlets/hot.py | 5 +++-- src/pcommerce/core/browser/viewlets/info.py | 20 +++++++++-------- src/pcommerce/core/browser/viewlets/new.py | 5 +++-- .../core/browser/viewlets/related.py | 18 ++++++++------- .../core/browser/viewlets/variation.py | 22 ++++++++++++------- 7 files changed, 52 insertions(+), 38 deletions(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index aa3315e..edaaa8c 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -5,7 +5,10 @@ Changelog 1.0b14 (unreleased) ------------------- -- Nothing changed yet. +* Improved viewlets to explicitly get the product view rather + than assuming they are rendered on it [simu] +* Fixed AttributeError in related products viewlet [simu] +* No longer use the deprecated jq alias in JavaScript [simu] 1.0b13 (2013-01-08) diff --git a/src/pcommerce/core/browser/viewlets/buy.py b/src/pcommerce/core/browser/viewlets/buy.py index 3f94e94..dbdfcb0 100644 --- a/src/pcommerce/core/browser/viewlets/buy.py +++ b/src/pcommerce/core/browser/viewlets/buy.py @@ -5,28 +5,29 @@ from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + class BuyViewlet(ViewletBase): index = ViewPageTemplateFile('buy.pt') - + def update(self): - ViewletBase.update(self) + super(BuyViewlet, self).update() self.product_view = getMultiAdapter((self.context, self.request), name=u'view') - + @property @memoize def product(self): return self.product_view.product - + @property @memoize def price(self): return self.product_view.price - + @property @memoize def base_price(self): return self.product_view.base_price - + @property @memoize def variations(self): @@ -42,5 +43,3 @@ def variations(self): type['variations'] = variations types.append(type) return types - - \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/hot.py b/src/pcommerce/core/browser/viewlets/hot.py index fba51c7..8529be8 100644 --- a/src/pcommerce/core/browser/viewlets/hot.py +++ b/src/pcommerce/core/browser/viewlets/hot.py @@ -11,9 +11,10 @@ from pcommerce.core.interfaces import IPricing, IProduct from pcommerce.core.currency import CurrencyAware + class HotViewlet(ViewletBase): index = ViewPageTemplateFile('hot.pt') - + def products(self): catalog = getToolByName(self.context, 'portal_catalog') portal_properties = getToolByName(self.context, 'portal_properties') @@ -51,4 +52,4 @@ def products(self): 'image': image, 'url': url} items.append(item) - return items \ No newline at end of file + return items diff --git a/src/pcommerce/core/browser/viewlets/info.py b/src/pcommerce/core/browser/viewlets/info.py index 0b03bf2..bba9a77 100644 --- a/src/pcommerce/core/browser/viewlets/info.py +++ b/src/pcommerce/core/browser/viewlets/info.py @@ -5,43 +5,45 @@ from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + class InfoViewlet(ViewletBase): index = ViewPageTemplateFile('info.pt') - + def update(self): + super(InfoViewlet, self).update() self.product_view = getMultiAdapter((self.context, self.request), name=u'view') - + @property @memoize def product(self): return self.product_view.product - + @property @memoize def image(self): return self.product_view.image - + @property @memoize def images(self): return self.product_view.images - + @property @memoize def price(self): return self.product_view.price - + @property @memoize def base_price(self): return self.product_view.base_price - + @property @memoize def offer(self): return self.product_view.offer - + @property @memoize def variations(self): - return self.product_view.variations \ No newline at end of file + return self.product_view.variations diff --git a/src/pcommerce/core/browser/viewlets/new.py b/src/pcommerce/core/browser/viewlets/new.py index 9e052a2..42be4f7 100644 --- a/src/pcommerce/core/browser/viewlets/new.py +++ b/src/pcommerce/core/browser/viewlets/new.py @@ -11,9 +11,10 @@ from pcommerce.core.interfaces import IPricing, IProduct from pcommerce.core.currency import CurrencyAware + class NewViewlet(ViewletBase): index = ViewPageTemplateFile('new.pt') - + def products(self): catalog = getToolByName(self.context, 'portal_catalog') portal_properties = getToolByName(self.context, 'portal_properties') @@ -51,4 +52,4 @@ def products(self): 'image': image, 'url': url} items.append(item) - return items \ No newline at end of file + return items diff --git a/src/pcommerce/core/browser/viewlets/related.py b/src/pcommerce/core/browser/viewlets/related.py index b7965b0..4558328 100644 --- a/src/pcommerce/core/browser/viewlets/related.py +++ b/src/pcommerce/core/browser/viewlets/related.py @@ -10,17 +10,19 @@ from pcommerce.core.interfaces import IPricing, IProduct from pcommerce.core.currency import CurrencyAware + class RelatedViewlet(ViewletBase): index = ViewPageTemplateFile('related.pt') - + def update(self): - self.view = getMultiAdapter((self.context, self.request), name=u'view') - + super(RelatedViewlet, self).update() + self.product_view = getMultiAdapter((self.context, self.request), name=u'view') + @property @memoize def product(self): - return self.view.product - + return self.product_view.product + @property @memoize def related_items(self): @@ -38,10 +40,10 @@ def related_items(self): i += 1 adapter = IPricing(item) image = None + url = item.absolute_url() if item.getImage(): image = {'caption': item.getImageCaption(), - 'thumb': '%s/%s' % (item.absolute_url(), width)} - url = item.getURL() + 'thumb': '%s/%s' % (url, width)} if item.portal_type in use_view_action: url += '/view' items.append({'uid': item.UID(), @@ -53,4 +55,4 @@ def related_items(self): 'offer': adapter.getPrice() < adapter.getBasePrice(), 'image': image, 'url': url}) - return items \ No newline at end of file + return items diff --git a/src/pcommerce/core/browser/viewlets/variation.py b/src/pcommerce/core/browser/viewlets/variation.py index ed1a4f1..8719e24 100644 --- a/src/pcommerce/core/browser/viewlets/variation.py +++ b/src/pcommerce/core/browser/viewlets/variation.py @@ -6,17 +6,23 @@ from Products.CMFCore.utils import getToolByName from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + from pcommerce.core.interfaces import IPricing, IProduct, IVariation from pcommerce.core.currency import CurrencyAware + class VariationViewlet(ViewletBase): index = ViewPageTemplateFile('variation.pt') - + + def update(self): + super(VariationViewlet, self).update() + self.product_view = getMultiAdapter((self.context, self.request), name=u'view') + @property @memoize def product(self): - return self.view.product - + return self.product_view.product + def variation_items(self): props = getToolByName(self.context, 'portal_properties').pcommerce_properties columns = int(props.getProperty('columns', 3)) @@ -24,23 +30,23 @@ def variation_items(self): width = width and 'image/thumb?width=%s' % width or 'image_thumb' items = [] i = 0 - + catalog = getToolByName(self.product, 'portal_catalog') variations = catalog(object_provides=IVariation.__identifier__, path={'query': '/'.join(self.product.getPhysicalPath())}) - + for variation in variations: col = i % columns + 1 i += 1 - + variation = variation.getObject() adapter = IPricing(self.product) - + if variation.UID() != self.context.UID(): image = None if variation.getImage(): image = {'caption': variation.getImageCaption(), 'thumb': '%s/%s' % (variation.absolute_url(), width)} - + items.append({'uid': variation.UID(), 'class': 'col%s' % col, 'title': '%s: %s' % (variation.getType(), variation.Title()), From 52cb114dd9a3fada2ec101e0e7489f36fc8c9844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=A4ser?= Date: Wed, 25 Sep 2013 09:52:56 +0200 Subject: [PATCH 23/27] Preparing release 1.0b14 --- docs/HISTORY.txt | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index edaaa8c..8f26575 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -2,7 +2,7 @@ Changelog ========= -1.0b14 (unreleased) +1.0b14 (2013-09-25) ------------------- * Improved viewlets to explicitly get the product view rather diff --git a/setup.py b/setup.py index 771d950..e11bc38 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages import os -version = '1.0b14.dev0' +version = '1.0b14' setup(name='pcommerce.core', version=version, From bde18c1edde103d70726ea7fbac5749262f0a04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=A4ser?= Date: Wed, 25 Sep 2013 09:58:21 +0200 Subject: [PATCH 24/27] Back to development: 1.0b15 --- docs/HISTORY.txt | 6 ++++++ setup.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/HISTORY.txt b/docs/HISTORY.txt index 8f26575..f944e31 100644 --- a/docs/HISTORY.txt +++ b/docs/HISTORY.txt @@ -2,6 +2,12 @@ Changelog ========= +1.0b15 (unreleased) +------------------- + +- Nothing changed yet. + + 1.0b14 (2013-09-25) ------------------- diff --git a/setup.py b/setup.py index e11bc38..041f05b 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages import os -version = '1.0b14' +version = '1.0b15.dev0' setup(name='pcommerce.core', version=version, From a63eaa57fe76eb4b34227cb7b3a8710f2598dd9f Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Mon, 24 Nov 2014 15:13:05 +0100 Subject: [PATCH 25/27] Small fixes --- .../core/browser/javascripts/as_customer.js | 8 -------- .../profiles/default/.propertiestool.xml.swp | Bin 12288 -> 0 bytes 2 files changed, 8 deletions(-) delete mode 100644 src/pcommerce/core/profiles/default/.propertiestool.xml.swp diff --git a/src/pcommerce/core/browser/javascripts/as_customer.js b/src/pcommerce/core/browser/javascripts/as_customer.js index 645164f..a8b5e10 100644 --- a/src/pcommerce/core/browser/javascripts/as_customer.js +++ b/src/pcommerce/core/browser/javascripts/as_customer.js @@ -1,9 +1,5 @@ -<<<<<<< HEAD:src/pcommerce/core/browser/javascripts/as_customer.js -$('document').ready(function() { -======= (function($) { $('document').ready(function() { ->>>>>>> No longer use the deprecated jq alias in JavaScript:pcommerce/core/browser/javascripts/as_customer.js var parents = $('#checkout .component:has(.as_customer)'); parents.each(function() { if($(this).find('.as_customer').is(':checked')) @@ -19,9 +15,5 @@ $('document').ready(function() { else parent.find('.address').show(); }); -<<<<<<< HEAD:src/pcommerce/core/browser/javascripts/as_customer.js }); -======= - }); })(jQuery); ->>>>>>> No longer use the deprecated jq alias in JavaScript:pcommerce/core/browser/javascripts/as_customer.js diff --git a/src/pcommerce/core/profiles/default/.propertiestool.xml.swp b/src/pcommerce/core/profiles/default/.propertiestool.xml.swp deleted file mode 100644 index cf1aea79132cb11ea65b595080fa8cbb3bd3e0d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI2!EVz)5Qe9S0|E-D@BpqkaH^d)DsV{CLnI^)NR<$9!?M?#WLxj9wO+SL4!{%e z3P`*McU}O*ky9&iD6hacc1p3@)X;K3%u2u3yITL=`RrLK%0#W_kDoXXyf$FF1@PkV z`_`4Em(aTgFwl}uiup6zM9WBwq}MmXPP|BuPFeqIYUsy&*H1+~_rpA~erj~ejTJnzS|{E}CZ{}>rilO%$Zdb+;Ucux zR$B#(yY8}cd+8Z*Ap%5z2oM1xKm>>Y5g-CY;6EZ@(*<~q@m{K8zEkxJwZ0lsM+Arf z5g-CYfCvx)B0vO)01+SpM1TnVg9O4DVEZb-XH@b3|Lphwx0?VTQSVSa)WHpa_o%0+ z%cu{F00wmr_2oLi8`L^#AL|C*qB^KU^!!?Re=7W`5dk7V1c(3;AOb{y2oQn4LZIX8 zXqz+J1qa)&qv=dlJUVt%DEWqKbgp8d1_9&BX0Bt$Db5OIT_?@W0Iwf~NygpodS_O5 zIxf9Wa7b$AT9a)SUQ8#sRPz`% zvO3OisO?2Y+|cfRlZXqivm}mO8=f7#(99Z4lzLt?2{6?e z!Wwe6qjOBGGROYhZeZE@O%zs|4+L%^v_h*uo0yxKYlLOxJXG~irzb(9c*`U$PMDeH z$OH{4aP Date: Tue, 7 Jul 2015 19:00:57 +0200 Subject: [PATCH 26/27] Fix differnt mails --- src/pcommerce/core/order.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pcommerce/core/order.py b/src/pcommerce/core/order.py index 97c3797..943e943 100644 --- a/src/pcommerce/core/order.py +++ b/src/pcommerce/core/order.py @@ -386,6 +386,16 @@ def send(self, orderid, lang=None): 'from_name': email_from_name, 'from_email': email_from} + mapping_user = {'orderid': order.orderid, + 'shipments': '\n\n'.join(shipments), + 'payment': translate(payment.mailInfo(order, lang), context=request, target_language=lang), + 'cart': '\n'.join(cart), + 'currency': order.currency, + 'address': address.mailInfoUser(request, lang), + 'name': address.firstname +' '+ address.lastname, + 'from_name': email_from_name, + 'from_email': email_from} + import ipdb; ipdb.set_trace() mailhost = getToolByName(self.context, 'MailHost') mailhost.secureSend(translate(self.getMessage(mapping), context=request, target_language=lang), mto=email_from, @@ -396,7 +406,7 @@ def send(self, orderid, lang=None): mapping.update({'shipments': '\n\n'.join(shipments_customer), 'payment': translate(payment.mailInfo(order, lang, customer=True), context=request, target_language=lang), 'address': address.mailInfo(request, lang, True)}) - mailhost.secureSend(translate(self.getMessageCustomer(mapping), context=request, target_language=lang), + mailhost.secureSend(translate(self.getMessageCustomer(mapping_user), context=request, target_language=lang), mto='%s <%s>' % (address.firstname +' '+ address.lastname, address.email), mfrom='%s <%s>' % (email_from_name, email_from), subject=translate(_('email_customer_title', default='Confirmation e-mail'), context=request, target_language=lang), From 2ac74320ece4f370e4cb1c722165bb9f000b8a19 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Tue, 7 Jul 2015 19:03:53 +0200 Subject: [PATCH 27/27] pdb fu --- src/pcommerce/core/order.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pcommerce/core/order.py b/src/pcommerce/core/order.py index 943e943..96174d6 100644 --- a/src/pcommerce/core/order.py +++ b/src/pcommerce/core/order.py @@ -395,7 +395,6 @@ def send(self, orderid, lang=None): 'name': address.firstname +' '+ address.lastname, 'from_name': email_from_name, 'from_email': email_from} - import ipdb; ipdb.set_trace() mailhost = getToolByName(self.context, 'MailHost') mailhost.secureSend(translate(self.getMessage(mapping), context=request, target_language=lang), mto=email_from,
    '.join(cells)) + return ''' + + + + + + + +
    %s
    %s
    ''' % ('
    '.join((translate(_(u'No'), context=self.request), + translate(_(u'Product'), context=self.request), + translate(_(u'Amount'), context=self.request), + translate(_(u'Price'), context=self.request), + translate(_(u'Price total'), context=self.request))), '
    '.join(rows)) + + def _shipmentids_converter(self, value, order): + return '
    • %s
    ' % '
  • '.join(value.keys()) + + def order_management_columns(self): + """Fields for order management table. """ + field_ids = [ + 'orderid', + 'userid', + 'date', + 'currency', + 'totalincl', + 'state', + ] + columns = [ column for column in self.order_fields() if \ + column['field_id'] in field_ids] + return columns + + def _massageData(self, field_id, value): + """Modify the field values (if needed) for displaying to humans. """ + # Convert the date (float) to a DateTime format. + if field_id == 'date': + value = DateTime(value) + value = self.translation_service.ulocalized_time( + value, long_format=True, time_only=None, + context=self.context, domain='plonelocales', + request=self.request) + # Convert order status to a translated string + if field_id == 'state': + value = self._translate_order_status_id(value) + return value + + def _get_order_data(self, order_nr, fields): + """Returns data of a single order as as a list of dictionaries, + suitable for displaying in a page template. + + Copies only the specified fields (which are defined like the + _order_fields list of dicts above. + + [ { 'id': ..., # field id + 'value: ..., # field value + 'name': ..., # field name (optional) + }, + ] + """ + r_order = self.registry.getOrder(order_nr) + order_data = [] + sort = 0 + for field in fields: + field_data = {} + field_id = field['field_id'] + field_data['id'] = field_id + value = getattr(r_order, field_id) + if field_id == self.sort_on: + sort = value + if field.has_key('field_converter'): + try: + value = field['field_converter'](value, r_order) + except: + pass + field_data['value'] = self._massageData(field_id, value) + field_data['name'] = field['field_name'] + order_data.append(field_data) + return order_data, sort + + @property + def batch(self): + """Returns data rows for order management table. """ + orders = [] + sorting = [] + # use only selected fields in the table + columns = self.order_management_columns() + for order_nr in self.registry.getOrders(): + data, sort = self._get_order_data(order_nr, columns) + index = len(orders) - 1 + while index >= 0 and sort < sorting[index]: + index -= 1 + sorting.insert(index + 1, sort) + orders.insert(index + 1, data) + if self.reverse: + orders.reverse() + pagesize = self.pagesize + b = Batch(orders, + pagesize=pagesize, + pagenumber=self.pagenumber) + return b + +class OrderDetails(ManageOrders): + """View order details. + + Subclassed from ManageOrders for easy code reuse. + """ + template = ViewPageTemplateFile('order_details.pt') + + def __call__(self): + self.request.set('disable_border', 1) + self.order_id = int(self.request.get('order_id')) + + # use all fields + fields = self.order_fields() + + self.order, sort = self._get_order_data( + self.order_id, + fields, + ) + return self.template() diff --git a/src/pcommerce/core/browser/portlets/__init__.py b/src/pcommerce/core/browser/portlets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/browser/portlets/cart.pt b/src/pcommerce/core/browser/portlets/cart.pt new file mode 100644 index 0000000..49f95b1 --- /dev/null +++ b/src/pcommerce/core/browser/portlets/cart.pt @@ -0,0 +1,30 @@ +
    + +
    + + Your shopping cart + +
    + +
    +
    +
    No of articles:
    +
    6
    +
    Total CHF:
    +
    120.00
    +
    +
    + +
    + + Check out + +
    +
    diff --git a/src/pcommerce/core/browser/portlets/cart.py b/src/pcommerce/core/browser/portlets/cart.py new file mode 100644 index 0000000..1c3b2a1 --- /dev/null +++ b/src/pcommerce/core/browser/portlets/cart.py @@ -0,0 +1,52 @@ +from zope.interface import implements +from zope.component import getMultiAdapter + +from plone.portlets.interfaces import IPortletDataProvider +from plone.app.portlets.portlets import base + +from Products.CMFCore.utils import getToolByName + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.currency import CurrencyAware +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.config import CheckOut +from pcommerce.core.interfaces import IShoppingCart + +class IShoppingCartPortlet(IPortletDataProvider): + """A portlet which renders a users shopping cart + """ + +class Assignment(base.Assignment): + implements(IShoppingCartPortlet) + + title = _(u'Shopping cart') + +class Renderer(base.Renderer): + + def update(self): + self.cart = IShoppingCart(self.context) + + @property + def portal_url(self): + portal_state = getMultiAdapter((self.context, self.request), name=u'plone_portal_state') + return portal_state.portal_url() + + @property + def size(self): + return self.cart.amount() + + @property + def price(self): + return CurrencyAware(self.cart.getPrice()) + + @property + def checkout(self): + return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) + + render = ViewPageTemplateFile('cart.pt') + +class AddForm(base.NullAddForm): + + def create(self): + return Assignment() diff --git a/src/pcommerce/core/browser/portlets/configure.zcml b/src/pcommerce/core/browser/portlets/configure.zcml new file mode 100644 index 0000000..fde64bf --- /dev/null +++ b/src/pcommerce/core/browser/portlets/configure.zcml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/prices.pt b/src/pcommerce/core/browser/prices.pt new file mode 100644 index 0000000..c44a1f0 --- /dev/null +++ b/src/pcommerce/core/browser/prices.pt @@ -0,0 +1,149 @@ + + + + + + + + + + +
    + + + Add price + + +

    + Additional prices +

    + +
    +
    Info
    +
    + You are currently looking at the prices of a variation of the product + Product title. +
    +
    + +

    + This product has no additional prices. To add a price press the + 'add' button or paste content from another location. +

    + +
    + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      Price  Modified  State   
    + + + + + + + + CHF 100.00 + + expired + + 08/19/2001 03:01 AM + + +   + + + + Edit + + + + Sharing +
    + + + + +
    + +
    +
    + + diff --git a/src/pcommerce/core/browser/prices.py b/src/pcommerce/core/browser/prices.py new file mode 100644 index 0000000..18dd5b5 --- /dev/null +++ b/src/pcommerce/core/browser/prices.py @@ -0,0 +1,58 @@ +from zope.component import getMultiAdapter +from zope.interface import implements + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from Products.CMFCore.utils import getToolByName + +from plone.memoize.instance import memoize +from plone.app.content.browser.interfaces import IFolderContentsView +from plone.app.content.browser.foldercontents import FolderContentsTable + +from pcommerce.core.currency import CurrencyAware +from pcommerce.core.interfaces import IPrice +from pcommerce.core.browser.product import Product + +class Prices(Product, FolderContentsTable): + """management view of all prices + """ + implements(IFolderContentsView) + + template = ViewPageTemplateFile('prices.pt') + + def __call__(self): + if self.request.get('prices', None): + prices = self.context.objectIds() + for price in self.request.get('prices', []): + if not isinstance(price, str) and price.id in prices: + self.context[price.id].setPrice(price.price) + self.context[price.id].reindexObject() + return self.template() + + @property + @memoize + def items(self): + catalog = getToolByName(self.context, 'portal_catalog') + plone_view = getMultiAdapter((self.context, self.request), name=u'plone') + utils = getToolByName(self.context, 'plone_utils') + wftool = getToolByName(self.context, 'portal_workflow') + results = catalog(object_provides=IPrice.__identifier__, path={'query': '/'.join(self.context.getPhysicalPath()), 'depth': 1}) + prices = [] + odd = True + for price in results: + prices.append({'uid': price.UID, + 'id': price.getId, + 'modified': plone_view.toLocalizedTime(price.ModificationDate, long_format=1), + 'state_title': wftool.getTitleForStateOnType(price.review_state, price.portal_type), + 'state_class': 'state-' + utils.normalizeString(price.review_state), + 'is_expired': self.context.isExpired(price), + 'title_or_id': price.pretty_title_or_id(), + 'table_row_class': odd and 'odd' or 'even', + 'raw_price': price.getPrice, + 'price': CurrencyAware(price.getPrice), + 'path': price.getPath, + 'relative_url': price.getURL(relative=True), + 'url': {'edit': '%s/edit' % price.getURL(), + 'sharing': '%s/@@sharing' % price.getURL()}}) + odd = not odd + return prices diff --git a/src/pcommerce/core/browser/product.pt b/src/pcommerce/core/browser/product.pt new file mode 100644 index 0000000..393e5a0 --- /dev/null +++ b/src/pcommerce/core/browser/product.pt @@ -0,0 +1,36 @@ + + + + + + +
    + +

    + Title +

    + +
    + +
    + Description +
    + +
    + +
    + +
    + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/product.py b/src/pcommerce/core/browser/product.py new file mode 100644 index 0000000..1dce9d9 --- /dev/null +++ b/src/pcommerce/core/browser/product.py @@ -0,0 +1,155 @@ +from Acquisition import aq_inner, aq_parent + +from Products.Five.browser import BrowserView +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from Products.CMFCore.utils import getToolByName + +from plone.memoize.instance import memoize + +from pcommerce.core.interfaces import IVariation, IPrice, IPricing, IImaging, ITaxes +from pcommerce.core.currency import CurrencyAware + +class Product(BrowserView): + """view of a product + """ + + template = ViewPageTemplateFile('product.pt') + + def __call__(self): + return self.template() + + @memoize + def title(self): + if IVariation.providedBy(self.context): + return '%s (%s: %s)' % (self.product.Title().decode('utf-8'), self.context.getType().decode('utf-8'), self.context.Title().decode('utf-8')) + return self.context.Title() + + @property + @memoize + def description(self): + return self.context.Description() or self.product.Description() + + @property + @memoize + def text(self): + return self.context.getText() or self.product.getText() + + @property + @memoize + def image(self): + props = getToolByName(self.context, 'portal_properties').pcommerce_properties + width = int(props.getProperty('thumb_width_detail', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + context = None + if self.context.getImage(): + context = self.context + elif self.product.getImage(): + context = self.product + if context is None: + return None + return {'caption': context.getImageCaption(), + 'thumb': '%s/%s' % (context.absolute_url(), width), + 'url': '%s/image_preview' % context.absolute_url()} + + @property + @memoize + def images(self): + images = [] + odd = False + i = 0 + + context = None + + if self.context.getImage(): + """ the variation have a image + """ + image = self.image + if image: + image['parity'] = 'odd' + images.append(image) + odd = True + i = 1 + context = self.context + elif not IImaging(self.context).getImages(): + """ the variation have not a image and not images in the content + """ + image = self.image + if image: + image['parity'] = 'odd' + images.append(image) + odd = True + i = 1 + context = self.product + else: + """ the variation have not a image but a images in the content + """ + context = self.context + + props = getToolByName(self.context, 'portal_properties').pcommerce_properties + width = int(props.getProperty('thumb_width_detail', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + + for image_raw in IImaging(context).getImages(): + image = {'url': '%s/image_preview' % (image_raw.getURL()), + 'thumb': '%s/%s' % (image_raw.getURL(), width), + 'caption': image_raw.Title + } + odd = not odd + if odd: + image['parity'] = 'odd' + else: + image['parity'] = 'even' + images.append(image) + i += 1 + + return images + + @property + @memoize + def product(self): + context = aq_inner(self.context) + if IVariation.providedBy(context): + return aq_parent(context) + return self.context + + @property + def price(self): + if IVariation.providedBy(self.context): + return CurrencyAware(IPricing(self.product).getPrice([aq_inner(self.context),])) + return CurrencyAware(IPricing(self.product).getPrice()) + + @property + def base_price(self): + if IVariation.providedBy(self.context): + return CurrencyAware(IPricing(self.product).getBasePrice([aq_inner(self.context),])) + return CurrencyAware(IPricing(self.product).getBasePrice()) + + @property + @memoize + def offer(self): + return self.price.getValue() < self.base_price.getValue() + + @property + def variations(self): + catalog = getToolByName(self.context, 'portal_catalog') + results = catalog(object_provides=IVariation.__identifier__, path={'query': '/'.join(self.product.getPhysicalPath())}) + variations = {} + for variation in results: + if not variations.has_key(variation.getType): + variations[variation.getType] = [] + if not variation.getAddPrice: + price_adapter = IPricing(variation.getObject()) + variations[variation.getType].append({ + 'uid': variation.UID, + 'name': variation.Title, + 'price': CurrencyAware(IPricing(self.product).getPrice([variation.getObject()])), + 'price_raw': IPricing(self.product).getPrice([variation.getObject()]), + 'base_price': CurrencyAware(variation.getAddPrice and self.base_price.getValue() + float(variation.getPrice) or price_adapter.getBasePrice()), + 'base_price_raw':variation.getAddPrice and self.base_price.getValue() + float(variation.getPrice) or price_adapter.getBasePrice(), + 'add_price': variation.getAddPrice and CurrencyAware(float(variation.getPrice)) or None, + 'add_price_raw': variation.getAddPrice and float(variation.getPrice) or None, }) + + + return [{'name': type[0], + 'variations': type[1]} for type in variations.items()] diff --git a/src/pcommerce/core/browser/variation.pt b/src/pcommerce/core/browser/variation.pt new file mode 100644 index 0000000..25d422e --- /dev/null +++ b/src/pcommerce/core/browser/variation.pt @@ -0,0 +1,46 @@ + + + + + + +
    + +

    + Title +

    + +
    +
    Info
    +
    + You are currently looking at a variation of the product + Product title. +
    +
    + +
    + +
    + Description +
    + +
    + +
    + +
    + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/variation.py b/src/pcommerce/core/browser/variation.py new file mode 100644 index 0000000..79555eb --- /dev/null +++ b/src/pcommerce/core/browser/variation.py @@ -0,0 +1,8 @@ +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.browser.product import Product + +class Variation(Product): + """view of a variation + """ + template = ViewPageTemplateFile('variation.pt') diff --git a/src/pcommerce/core/browser/variations.pt b/src/pcommerce/core/browser/variations.pt new file mode 100644 index 0000000..f9d7a66 --- /dev/null +++ b/src/pcommerce/core/browser/variations.pt @@ -0,0 +1,41 @@ + + + + + + + + + + +
    + + + Add variation + + +

    + Variations +

    + +
    +
    + +
    +
    + + + + diff --git a/src/pcommerce/core/browser/variations.py b/src/pcommerce/core/browser/variations.py new file mode 100644 index 0000000..11b6f73 --- /dev/null +++ b/src/pcommerce/core/browser/variations.py @@ -0,0 +1,11 @@ +from plone.app.content.browser.foldercontents import FolderContentsView, FolderContentsTable + +from pcommerce.core.interfaces import IVariation + +class Variations(FolderContentsView): + """management view of all variations + """ + + def contents_table(self): + table = FolderContentsTable(self.context, self.request, {'object_provides': IVariation.__identifier__}) + return table.render() \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/__init__.py b/src/pcommerce/core/browser/viewlets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/browser/viewlets/buy.pt b/src/pcommerce/core/browser/viewlets/buy.pt new file mode 100644 index 0000000..db8f6e2 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/buy.pt @@ -0,0 +1,22 @@ +
    +
    + + + + + + + + + +
    +
    diff --git a/src/pcommerce/core/browser/viewlets/buy.py b/src/pcommerce/core/browser/viewlets/buy.py new file mode 100644 index 0000000..3f94e94 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/buy.py @@ -0,0 +1,46 @@ +from zope.component import getMultiAdapter + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +class BuyViewlet(ViewletBase): + index = ViewPageTemplateFile('buy.pt') + + def update(self): + ViewletBase.update(self) + self.product_view = getMultiAdapter((self.context, self.request), name=u'view') + + @property + @memoize + def product(self): + return self.product_view.product + + @property + @memoize + def price(self): + return self.product_view.price + + @property + @memoize + def base_price(self): + return self.product_view.base_price + + @property + @memoize + def variations(self): + types = [] + for type in self.product_view.variations: + variations = [] + for variation in type['variations']: + if self.context.Title() == variation['name']: + variation['selected'] = True + else: + variation['selected'] = False + variations.append(variation) + type['variations'] = variations + types.append(type) + return types + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/configure.zcml b/src/pcommerce/core/browser/viewlets/configure.zcml new file mode 100644 index 0000000..4b9b92b --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/configure.zcml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/hot.pt b/src/pcommerce/core/browser/viewlets/hot.pt new file mode 100644 index 0000000..0b1edc6 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/hot.pt @@ -0,0 +1,10 @@ +
    +

    + Product highlights +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/hot.py b/src/pcommerce/core/browser/viewlets/hot.py new file mode 100644 index 0000000..fba51c7 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/hot.py @@ -0,0 +1,54 @@ +from zope.component import getMultiAdapter +import random + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.CMFCore.utils import getToolByName + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.interfaces import IPricing, IProduct +from pcommerce.core.currency import CurrencyAware + +class HotViewlet(ViewletBase): + index = ViewPageTemplateFile('hot.pt') + + def products(self): + catalog = getToolByName(self.context, 'portal_catalog') + portal_properties = getToolByName(self.context, 'portal_properties') + use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) + props = portal_properties.pcommerce_properties + columns = int(props.getProperty('hot_columns', 3)) + no = int(props.getProperty('no_hot_products', 6)) + width = int(props.getProperty('thumb_width_hot_products', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + results = list(catalog(object_provides=IProduct.__identifier__, hot=True)) + if not results: + return None + items = [] + i = 0 + while len(items) < no and len(results): + item = results.pop(random.randrange(len(results))) + object = item.getObject() + col = i % columns + 1 + i += 1 + adapter = IPricing(object) + image = None + if object.getImage(): + image = {'caption': object.getImageCaption(), + 'thumb': '%s/%s' % (item.getURL(), width)} + url = item.getURL() + if item.portal_type in use_view_action: + url += '/view' + item = {'uid': item.UID, + 'class': 'col%s' % col, + 'title': item.Title, + 'description': item.Description, + 'price': CurrencyAware(adapter.getPrice()), + 'base_price': CurrencyAware(adapter.getBasePrice()), + 'offer': adapter.getPrice() < adapter.getBasePrice(), + 'image': image, + 'url': url} + items.append(item) + return items \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/info.pt b/src/pcommerce/core/browser/viewlets/info.pt new file mode 100644 index 0000000..6c6edd7 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/info.pt @@ -0,0 +1,19 @@ +
    + +
    + + + + +
    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/info.py b/src/pcommerce/core/browser/viewlets/info.py new file mode 100644 index 0000000..0b03bf2 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/info.py @@ -0,0 +1,47 @@ +from zope.component import getMultiAdapter + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +class InfoViewlet(ViewletBase): + index = ViewPageTemplateFile('info.pt') + + def update(self): + self.product_view = getMultiAdapter((self.context, self.request), name=u'view') + + @property + @memoize + def product(self): + return self.product_view.product + + @property + @memoize + def image(self): + return self.product_view.image + + @property + @memoize + def images(self): + return self.product_view.images + + @property + @memoize + def price(self): + return self.product_view.price + + @property + @memoize + def base_price(self): + return self.product_view.base_price + + @property + @memoize + def offer(self): + return self.product_view.offer + + @property + @memoize + def variations(self): + return self.product_view.variations \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/new.pt b/src/pcommerce/core/browser/viewlets/new.pt new file mode 100644 index 0000000..ca6ce39 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/new.pt @@ -0,0 +1,10 @@ +
    +

    + New products in our shop +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/new.py b/src/pcommerce/core/browser/viewlets/new.py new file mode 100644 index 0000000..9e052a2 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/new.py @@ -0,0 +1,54 @@ +import random +from zope.component import getMultiAdapter + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.CMFCore.utils import getToolByName + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.interfaces import IPricing, IProduct +from pcommerce.core.currency import CurrencyAware + +class NewViewlet(ViewletBase): + index = ViewPageTemplateFile('new.pt') + + def products(self): + catalog = getToolByName(self.context, 'portal_catalog') + portal_properties = getToolByName(self.context, 'portal_properties') + use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) + props = portal_properties.pcommerce_properties + columns = int(props.getProperty('new_columns', 2)) + no = int(props.getProperty('no_new_products', 2)) + width = int(props.getProperty('thumb_width_new_products', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + results = list(catalog(object_provides=IProduct.__identifier__, new=True)) + if not results: + return None + items = [] + i = 0 + while len(items) < no and len(results): + item = results.pop(random.randrange(len(results))) + object = item.getObject() + col = i % columns + 1 + i += 1 + adapter = IPricing(object) + image = None + if object.getImage(): + image = {'caption': object.getImageCaption(), + 'thumb': '%s/%s' % (item.getURL(), width)} + url = item.getURL() + if item.portal_type in use_view_action: + url += '/view' + item = {'uid': item.UID, + 'class': 'col%s' % col, + 'title': item.Title, + 'description': item.Description, + 'price': CurrencyAware(adapter.getPrice()), + 'base_price': CurrencyAware(adapter.getBasePrice()), + 'offer': adapter.getPrice() < adapter.getBasePrice(), + 'image': image, + 'url': url} + items.append(item) + return items \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/processor.py b/src/pcommerce/core/browser/viewlets/processor.py new file mode 100644 index 0000000..d1a4c5f --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/processor.py @@ -0,0 +1,52 @@ +from plone.app.layout.viewlets.common import ViewletBase + +from Products.CMFCore.utils import getToolByName + +from Products.statusmessages.interfaces import IStatusMessage + +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.interfaces import IShoppingCart + +class ProcessorViewlet(ViewletBase): + + def update(self): + self.statusmessages = IStatusMessage(self.request) + try: + amount = int(self.request.get('cartAmount', 1)) + except: + self.statusmessages.addStatusMessage(_(u'Please specify an amount'), 'error') + return + + self.added = self.removed = 0 + adapter = IShoppingCart(self.context) + + if self.request.get('cartAdd', None): + self.added += adapter.add(self.request.get('cartAdd', None), amount) + + elif self.request.get('cartVariation', None): + self.added += adapter.addVariation(self.request.get('cartVariation', None), amount) + if not self.added: + self.statusmessages.addStatusMessage(_(u'Please select a variation'), 'error') + + elif self.request.get('cartRemove', None): + self.removed -= adapter.remove(self.request.get('cartRemove', None), self.request.get('cartRemoveAmount', None)) + + elif self.request.get('cartEdit', None): + a, r = adapter.edit(self.request.get('cartEdit', None)) + self.added += a + self.removed += r + + self.addStatusMessages() + + def index(self): + return '' + + def addStatusMessages(self): + if self.added > 1: + self.statusmessages.addStatusMessage(_(u'Added ${count} items to cart', mapping={'count': self.added}), 'info') + elif self.added == 1: + self.statusmessages.addStatusMessage(_(u'Added item to cart'), 'info') + if self.removed > 1: + self.statusmessages.addStatusMessage(_(u'Removed ${count} items from cart', mapping={'count': self.removed}), 'info') + elif self.removed == 1: + self.statusmessages.addStatusMessage(_(u'Removed item from cart'), 'info') diff --git a/src/pcommerce/core/browser/viewlets/related.pt b/src/pcommerce/core/browser/viewlets/related.pt new file mode 100644 index 0000000..fb8032c --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/related.pt @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/related.py b/src/pcommerce/core/browser/viewlets/related.py new file mode 100644 index 0000000..b7965b0 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/related.py @@ -0,0 +1,56 @@ +from zope.component import getMultiAdapter + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.CMFCore.utils import getToolByName + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile + +from pcommerce.core.interfaces import IPricing, IProduct +from pcommerce.core.currency import CurrencyAware + +class RelatedViewlet(ViewletBase): + index = ViewPageTemplateFile('related.pt') + + def update(self): + self.view = getMultiAdapter((self.context, self.request), name=u'view') + + @property + @memoize + def product(self): + return self.view.product + + @property + @memoize + def related_items(self): + portal_properties = getToolByName(self.context, 'portal_properties') + use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) + props = portal_properties.pcommerce_properties + columns = int(props.getProperty('columns', 3)) + width = int(props.getProperty('thumb_width', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + items = [] + i = 0 + for item in self.product.getRelatedItems(): + if IProduct.providedBy(item): + col = i % columns + 1 + i += 1 + adapter = IPricing(item) + image = None + if item.getImage(): + image = {'caption': item.getImageCaption(), + 'thumb': '%s/%s' % (item.absolute_url(), width)} + url = item.getURL() + if item.portal_type in use_view_action: + url += '/view' + items.append({'uid': item.UID(), + 'class': 'col%s' % col, + 'title': item.Title(), + 'description': item.Description(), + 'price': CurrencyAware(adapter.getPrice()), + 'base_price': CurrencyAware(adapter.getBasePrice()), + 'offer': adapter.getPrice() < adapter.getBasePrice(), + 'image': image, + 'url': url}) + return items \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/variation.pt b/src/pcommerce/core/browser/viewlets/variation.pt new file mode 100644 index 0000000..f642fd4 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/variation.pt @@ -0,0 +1,10 @@ +
    +

    + Product variations +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/src/pcommerce/core/browser/viewlets/variation.py b/src/pcommerce/core/browser/viewlets/variation.py new file mode 100644 index 0000000..ed1a4f1 --- /dev/null +++ b/src/pcommerce/core/browser/viewlets/variation.py @@ -0,0 +1,53 @@ +from zope.component import getMultiAdapter + +from plone.memoize.instance import memoize +from plone.app.layout.viewlets.common import ViewletBase + +from Products.CMFCore.utils import getToolByName + +from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from pcommerce.core.interfaces import IPricing, IProduct, IVariation +from pcommerce.core.currency import CurrencyAware + +class VariationViewlet(ViewletBase): + index = ViewPageTemplateFile('variation.pt') + + @property + @memoize + def product(self): + return self.view.product + + def variation_items(self): + props = getToolByName(self.context, 'portal_properties').pcommerce_properties + columns = int(props.getProperty('columns', 3)) + width = int(props.getProperty('thumb_width', 0)) + width = width and 'image/thumb?width=%s' % width or 'image_thumb' + items = [] + i = 0 + + catalog = getToolByName(self.product, 'portal_catalog') + variations = catalog(object_provides=IVariation.__identifier__, path={'query': '/'.join(self.product.getPhysicalPath())}) + + for variation in variations: + col = i % columns + 1 + i += 1 + + variation = variation.getObject() + adapter = IPricing(self.product) + + if variation.UID() != self.context.UID(): + image = None + if variation.getImage(): + image = {'caption': variation.getImageCaption(), + 'thumb': '%s/%s' % (variation.absolute_url(), width)} + + items.append({'uid': variation.UID(), + 'class': 'col%s' % col, + 'title': '%s: %s' % (variation.getType(), variation.Title()), + 'description': variation.Description() or self.product.Description(), + 'price': CurrencyAware(adapter.getPrice([variation, ])), + 'base_price': CurrencyAware(adapter.getBasePrice()), + 'offer': adapter.getPrice([variation, ]) < adapter.getBasePrice(), + 'image': image, + 'url': variation.absolute_url()}) + return items diff --git a/src/pcommerce/core/cart.py b/src/pcommerce/core/cart.py new file mode 100644 index 0000000..554544f --- /dev/null +++ b/src/pcommerce/core/cart.py @@ -0,0 +1,256 @@ +from zope.interface import implements, Interface +from zope.component import adapts + +from Acquisition import aq_parent +from Products.CMFCore.utils import getToolByName + +from pcommerce.core.currency import CurrencyAware +from pcommerce.core import interfaces + +SESSION_KEY = 'pcommerce.core.cart' + + +class Cart(object): + """ + """ + _items = {} + + def __len__(self): + return len(self._items) + + def __getitem__(self, key): + return self._items[key] + + def __setitem__(self, key, value): + if key: + self._items[key] = value + self._save() + + def __contains__(self, key): + return key in self._items + + def has_key(self, key): + return key in self._items + + def items(self): + return self._items.items() + + +class ShoppingCart(Cart): + """ An adapter to handle a shopping cart + + the adapter supports the following standard python methods: + + len(ShoppingCart) + ShoppingCart.has_key(key) + ShoppingCart.items() + ShoppingCart[key] + ShoppingCart[key] = value + del(ShoppingCart[key]) + """ + implements(interfaces.IShoppingCart) + adapts(Interface) + + def __init__(self, context): + self.context = context + # avoid creating a session implicitly + session = self.context.session_data_manager.getSessionData(create=0) + self._items = session and session.get(SESSION_KEY, {}) or {} + + def __delitem__(self, key): + del(self._items[key]) + self._save() + + def amount(self): + """ returns amount of products in the cart + """ + size = 0 + for uid, amount in self.items(): + size += amount + return size + + def getPrice(self): + """ returns the total price of all products in the cart + """ + price = 0.0 + products = self.getProducts() + for product in products: + price += product['price_total_raw'] + return price + + def getProducts(self): + """ returns list of products currently in the cart + """ + catalog = getToolByName(self.context, 'uid_catalog') + portal_properties = getToolByName(self.context, 'portal_properties') + use_view_action = portal_properties.site_properties.getProperty('typesUseViewActionInListings', ()) + + products = [] + for uid, amount in self.items(): + results = [product.getObject() for product in catalog( + object_provides=interfaces.IProduct.__identifier__, UID=uid)] + if results: + variations = [] + variations_raw = [] + product = None + for result in results: + if interfaces.IVariation.providedBy(result): + variations_raw.append(result) + variation = {'type': result.getType(), + 'name': result.Title(), + 'no': result.getNo(), + 'add_price': None, + 'add_price_raw': None, + 'uid': result.UID(), + 'object': result} + if result.getAddPrice(): + variation['add_price_raw'] =\ + float(result.getPrice()) + variation['add_price'] =\ + CurrencyAware(result.getPrice()) + variations.append(variation) + if not product: + product = aq_parent(result) + else: + product = result + url = product.absolute_url() + if product.portal_type in use_view_action: + product_url = url + '/view' + else: + product_url = url + price = interfaces.IPricing(product).getPrice(variations_raw) + products.append({'title': product.Title(), + 'no': product.getNo(), + 'description': product.Description(), + 'price': CurrencyAware(price), + 'price_raw': price, + 'price_total': CurrencyAware(price * amount), + 'price_total_raw': price * amount, + 'uid': product.UID(), + 'amount': amount, + 'url': product_url, + 'image_url': url, + 'variations': variations, + 'object': product + }) + return products + + def addVariation(self, item, amount=1): + """ adds a variation of a product to the cart + + possible values of item: + - a uid + - a list of uids (combination of multiple variations) + """ + uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( + 'UID') + if not isinstance(item, basestring): + item.sort() + for i in item: + if not i in uids: + return 0 + item = tuple(item) + elif not item in uids: + return 0 + + return self._addItem({'uid': item, + 'amount': int(amount)}) + + def add(self, items, amount=1): + """ adds products to the cart + + possible values of items: + - a uid + - list of uids (multiple products) + - list of dicts with 'uid' and 'amount' key + (multiple products with different amounts) + """ + added = 0 + if isinstance(items, basestring): + items = ({'uid': items, + 'amount': int(amount)},) + uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( + 'UID') + for item in items: + if isinstance(item, basestring): + item = {'uid': item, + 'amount': int(amount)} + if item['uid'] in uids: + added += self._addItem(item) + return added + + def remove(self, items, amount=None): + """ removes products from the cart + + possible values of items: + - a uid + - list of uids (multiple products) + - list of dicts with 'uid' and 'amount' keys + (multiple products with different amounts) + """ + removed = 0 + if isinstance(items, basestring): + items = ({'uid': items, + 'amount': amount},) + for item in items: + if isinstance(item, basestring): + item = {'uid': item, + 'amount': amount} + if item['uid'] in self: + if not item['amount'] or int(item['amount']) is 0 or \ + int(item['amount']) >= self[item['uid']]: + removed += self[item['uid']] + del self[item['uid']] + else: + removed += int(item['amount']) + self[item['uid']] = self[item['uid']] - int(item['amount']) + return removed + + def edit(self, items): + """ edits the cart + + items has to be a list of dicts with keys 'uid', 'amount' + and 'remove' + """ + added = removed = 0 + uids = getToolByName(self.context, 'uid_catalog').uniqueValuesFor( + 'UID') + for item in items: + if 'variation' in item: + item['variation'].sort() + if item['uid'] in uids and int(item['amount']) > 0 and \ + (not 'remove' in item or not item['remove']): + if 'variation' in item and item['variation']: + item = {'uid': tuple(item['variation']), + 'amount': item['amount']} + if item['uid'] in self: + removed += self[item['uid']] > int(item['amount']) \ + and self[item['uid']] - int(item['amount']) or 0 + added += self[item['uid']] < int(item['amount']) \ + and int(item['amount']) - self[item['uid']] or 0 + else: + added += int(item['amount']) + self[item['uid']] = int(item['amount']) + if ('remove' in item and item['remove']) or \ + int(item['amount']) is 0: + uid = 'variation' in item and tuple(item['variation']) or\ + item['uid'] + removed += self.remove([{'uid': uid, + 'amount': None}]) + return added, removed + + def clear(self): + """ clears the cart + """ + self._items = {} + self._save() + + def _addItem(self, item): + added = item['amount'] + if item['uid'] in self: + item['amount'] += self[item['uid']] + self[item['uid']] = item['amount'] + return added + + def _save(self): + self.context.REQUEST.SESSION.set(SESSION_KEY, self._items) diff --git a/src/pcommerce/core/charge.py b/src/pcommerce/core/charge.py new file mode 100644 index 0000000..bc3aec1 --- /dev/null +++ b/src/pcommerce/core/charge.py @@ -0,0 +1,17 @@ +from persistent import Persistent + +from zope.interface import implements + +from pcommerce.core.interfaces import IChargeData + +class ChargeData(Persistent): + """ Base implementation of a charge data object + """ + implements(IChargeData) + + title = u'' + price = 0.0 + + def __init__(self, title, price): + self.title = title + self.price = price \ No newline at end of file diff --git a/src/pcommerce/core/config.py b/src/pcommerce/core/config.py new file mode 100644 index 0000000..897c7a4 --- /dev/null +++ b/src/pcommerce/core/config.py @@ -0,0 +1,46 @@ +from AccessControl import ModuleSecurityInfo +from Products.CMFCore.permissions import setDefaultRoles + +security = ModuleSecurityInfo('pcommerce.core.config') + +security.declarePublic('AddProduct') +AddProduct = 'PCommerce: Add Product' +setDefaultRoles(AddProduct, ('Manager','Contributer','Owner',)) + +security.declarePublic('AddVariation') +AddVariation = 'PCommerce: Add Variation' +setDefaultRoles(AddVariation, ('Manager','Contributer','Owner',)) + +security.declarePublic('AddImage') +AddVariation = 'PCommerce: Add Image' +setDefaultRoles(AddVariation, ('Manager','Contributer','Owner',)) + +security.declarePublic('AddPrice') +AddPrice = 'PCommerce: Add Price' +setDefaultRoles(AddPrice, ('Manager','Contributer','Owner',)) + +security.declarePublic('AddToCart') +AddToCart = 'PCommerce: Add to Cart' +setDefaultRoles(AddToCart, ('Anonymous', 'Authenticated',)) + +security.declarePublic('CheckOut') +CheckOut = 'PCommerce: Check out' +setDefaultRoles(CheckOut, ('Authenticated',)) + +security.declarePublic('ManageOrders') +ManageOrders = 'PCommerce: Manage Orders' +setDefaultRoles(ManageOrders, ('Manager',)) + +permissions = {'Product': AddProduct, + 'Variation': AddVariation, + 'Price': AddPrice} + +INITIALIZED = 1 +SENT = 2 +PROCESSED = 3 +FAILED = 4 +CANCELED = 5 + +PROJECTNAME = "pcommerce.core" + +product_globals = globals() diff --git a/src/pcommerce/core/configure.zcml b/src/pcommerce/core/configure.zcml new file mode 100644 index 0000000..25df042 --- /dev/null +++ b/src/pcommerce/core/configure.zcml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/content/__init__.py b/src/pcommerce/core/content/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/content/price.py b/src/pcommerce/core/content/price.py new file mode 100644 index 0000000..cca06bd --- /dev/null +++ b/src/pcommerce/core/content/price.py @@ -0,0 +1,42 @@ +"""Price content type +""" + +from AccessControl import ClassSecurityInfo + +from zope.interface import implements + +from Products.Archetypes.public import * + +from pcommerce.core.interfaces import IPrice +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.config import PROJECTNAME + +PriceSchema = BaseContent.schema.copy() + Schema(( + + FixedPointField( + name='price', + required=1, + languageIndependent=True, + widget=DecimalWidget( + label=_(u'Price'), + ) + ), + +)) + +for field in ('description', 'creators','allowDiscussion','contributors','location','subject','language','rights','title',): + if PriceSchema.has_key(field): + PriceSchema[field].widget.visible = 0 + +PriceSchema['title'].required = False + +class Price(BaseContent): + """ A Price + """ + implements(IPrice) + + portal_type = meta_type = "Price" + schema = PriceSchema + _at_rename_after_creation = False + +registerType(Price, PROJECTNAME) \ No newline at end of file diff --git a/src/pcommerce/core/content/product.py b/src/pcommerce/core/content/product.py new file mode 100644 index 0000000..7aee01f --- /dev/null +++ b/src/pcommerce/core/content/product.py @@ -0,0 +1,136 @@ +"""Product content-type +""" + +from AccessControl import ClassSecurityInfo + +from zope.interface import implements + +try: + from Products.LinguaPlone.public import * +except ImportError: + # No multilingual support + from Products.Archetypes.public import * + +from Products.validation import V_REQUIRED + +from Products.CMFCore.permissions import View + +from Products.ATContentTypes.content.document import ATDocumentBase, ATDocumentSchema + +from pcommerce.core.interfaces import IProduct +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.config import PROJECTNAME + +from Products.CMFPlone.interfaces import INonStructuralFolder +from Products.CMFPlone import PloneMessageFactory as _p + +from zope.schema.interfaces import IVocabularyFactory + +ProductSchema = ATDocumentSchema.copy() + Schema(( + + StringField( + name='no', + searchable=1, + widget=StringWidget( + label=_('No'), + ) + ), + + FixedPointField( + name='price', + languageIndependent=True, + widget=DecimalWidget( + label=_(u'Price'), + ) + ), + + BooleanField( + name='new', + languageIndependent=True, + widget=BooleanWidget( + label=_(u'New product'), + ) + ), + + BooleanField( + name='hot', + languageIndependent=True, + widget=BooleanWidget( + label=_(u'Hot product'), + ) + ), + + LinesField( + name='shipments', + required = True, + multiValued = True, + widget = MultiSelectionWidget(label = _(u'label_shipment_methods', default=u'Shipment methods'), + description = _(u'description_shipment_methods', default=u'Shipment methods for this product'), + format = 'checkbox', + ), + vocabulary_factory = u"pcommerce.core.vocabulary.shipments" + ), + + ImageField( + name='image', + languageIndependent=True, + swallowResizeExceptions=True, + max_size='no', + sizes={'large' : (768, 768), + 'preview' : (400, 400), + 'mini' : (200, 200), + 'thumb' : (128, 128), + 'tile' : (64, 64), + 'icon' : (32, 32), + 'listing' : (16, 16), + }, + validators=(('isNonEmptyFile', V_REQUIRED), + ('checkImageMaxSize', V_REQUIRED),), + widget=ImageWidget(label= _p(u'label_news_image', default=u'Image'), + show_content_type = False,), + ), + + StringField( + name='imageCaption', + required = False, + searchable = True, + widget = StringWidget(description = '', + label = _p(u'label_image_caption', default=u'Image Caption'), + size = 40) + ), + +)) + +for field in ('creators','contributors','location','subject','language','rights','presentation', 'tableContents',): + if ProductSchema.has_key(field): + ProductSchema[field].widget.visible = 0 + +ProductSchema['excludeFromNav'].default = 1 +ProductSchema.changeSchemataForField('relatedItems', 'default') +ProductSchema.moveField('no', after='title') +ProductSchema.moveField('price', after='no') +ProductSchema.moveField('hot', after='description') +ProductSchema.moveField('new', after='hot') +ProductSchema.moveField('shipments', after='new') +ProductSchema.moveField('image', after='shipments') +ProductSchema.moveField('imageCaption', after='image') + +class Product(OrderedBaseFolder, ATDocumentBase): + """ A product + """ + implements(IProduct, INonStructuralFolder) + + portal_type = meta_type = "Product" + schema = ProductSchema + security = ClassSecurityInfo() + _at_rename_after_creation = True + + security.declareProtected(View, 'tag') + def tag(self, **kwargs): + """Generate image tag using the api of the ImageField + """ + if 'title' not in kwargs: + kwargs['title'] = self.getImageCaption() + return self.getField('image').tag(self, **kwargs) + +registerType(Product, PROJECTNAME) \ No newline at end of file diff --git a/src/pcommerce/core/content/variation.py b/src/pcommerce/core/content/variation.py new file mode 100644 index 0000000..a686537 --- /dev/null +++ b/src/pcommerce/core/content/variation.py @@ -0,0 +1,62 @@ +"""Variation content-type +""" +from zope.interface import implements + +try: + from Products.LinguaPlone.public import * +except ImportError: + # No multilingual support + from Products.Archetypes.public import * + +from Products.SingleKeywordWidget.widget import SingleKeywordWidget + +from pcommerce.core.content.product import Product, ProductSchema + +from pcommerce.core.interfaces import IVariation +from pcommerce.core import PCommerceMessageFactory as _ +from pcommerce.core.config import PROJECTNAME + +VariationSchema = Schema(( + + StringField( + name='type', + required=1, + searchable=True, + widget=SingleKeywordWidget( + label=_(u'Type'), + format='radio', + ) + ), + + BooleanField( + name='addPrice', + languageIndependent=True, + widget=BooleanWidget( + label=_(u'Additional price'), + ) + ), + +)) + ProductSchema.copy() + +VariationSchema['creators'].widget.visible = 0 +VariationSchema.changeSchemataForField('no', 'overrides') +VariationSchema.changeSchemataForField('text', 'overrides') +VariationSchema.changeSchemataForField('relatedItems', 'overrides') +VariationSchema.moveField('title', before='type') +VariationSchema.moveField('addPrice', after='price') +VariationSchema.moveField('effectiveDate', after='imageCaption') +VariationSchema.moveField('expirationDate', after='effectiveDate') + + + +VariationSchema['price'].widget.description = _(u'description_price', default=u'If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination.') + +class Variation(Product): + """ A variation of a product + """ + implements(IVariation) + + portal_type = meta_type = "Variation" + schema = VariationSchema + +registerType(Variation, PROJECTNAME) diff --git a/src/pcommerce/core/currency.py b/src/pcommerce/core/currency.py new file mode 100644 index 0000000..ab23b02 --- /dev/null +++ b/src/pcommerce/core/currency.py @@ -0,0 +1,74 @@ +from Products.CMFCore.utils import getToolByName +from zope.component import getSiteManager + +try: + from Products.CurrencyUtility.currency import CurrencyAware as CurrencyAwareBase +except: + # CurrencyUtility not available + + import math + + + class CurrencyAwareBase(object): + """helper class to convert values between currencies""" + + value = 0 + context = None + + def __str__(self): + return self.toString() + + def __init__(self, value, currency=None, rounding=None): + self.value = float(value) + if rounding is not None: + self.rounding = rounding + else: + rounding = 0.05 # default value, round to 5 cents + + def getContext(self): + """returns the context""" + if self.context is None: + self.context = getSiteManager() + return self.context + + def getCurrencySymbol(self): + """return the currency registered in site_properties""" + props = getToolByName(self.getContext(), 'portal_properties').site_properties + return props.getProperty('currency', '') + + def getValue(self, currency=None): + """returns the value in the appropriate currency""" + return self.value + + def getRoundedValue(self, currency=None): + """returns the value in the appropriate currency rounded to 0.05""" + value = self.getValue(currency) + factor = 1.0 / self.rounding + return float(int(math.ceil(value*factor)))/factor + + def toString(self, currency=None): + """returns the value in the appropriate currency rounded to 0.05 including the symbol""" + return "%s %0.2f" % (self.getCurrencySymbol(), self.getRoundedValue()) + + def valueToString(self, currency=None): + """returns the value in the appropriate currency rounded to 0.05""" + return "%0.2f" % self.getRoundedValue() + + def safeToString(self, currency=None): + """returns the value in the appropriate currency rounded to 0.05 including the currency-short-name""" + return "%s %0.2f" % (self.getCurrencySymbol(), self.getRoundedValue()) + + +class CurrencyAware(CurrencyAwareBase): + """wrapper around CurrencyAware, so we can use proper rounding""" + + def __init__(self, value, currency=None): + """ + retrieve the rounding from the properties, and + call base init method + """ + context = getSiteManager() + props = getToolByName(context, 'portal_properties').pcommerce_properties + rounding_cents = int(props.getProperty('rounding_cents', 5)) + rounding = rounding_cents * 0.01 + super(CurrencyAware, self).__init__(value, currency, rounding) diff --git a/src/pcommerce/core/data.py b/src/pcommerce/core/data.py new file mode 100644 index 0000000..b425f6d --- /dev/null +++ b/src/pcommerce/core/data.py @@ -0,0 +1,23 @@ +from persistent import Persistent + +from zope.interface import implements + +from pcommerce.core.interfaces import IPaymentData, IShipmentData + +class BaseData(Persistent): + pretaxcharge = 0.0 + posttaxcharge = 0.0 + + def __init__(self, id, pretaxcharge=0.0, posttaxcharge=0.0, **kwargs): + self.id = id + self.pretaxcharge = pretaxcharge + self.posttaxcharge = posttaxcharge + for key, value in kwargs.items(): + setattr(self, key, value) + +class PaymentData(BaseData): + implements(IPaymentData) + +class ShipmentData(BaseData): + implements(IShipmentData) + diff --git a/src/pcommerce/core/events.py b/src/pcommerce/core/events.py new file mode 100644 index 0000000..4a96e66 --- /dev/null +++ b/src/pcommerce/core/events.py @@ -0,0 +1,39 @@ +from zope.interface import implements + +from pcommerce.core import interfaces + +class OrderEvent(object): + + def __init__(self, registry, order): + self.registry = registry + self.order = order + +class OrderProcessingSuccessfulEvent(OrderEvent): + implements(interfaces.IOrderProcessingSuccessfulEvent) + +class OrderProcessingFailedEvent(OrderEvent): + implements(interfaces.IOrderProcessingFailedEvent) + +class OrderProcessedEvent(OrderEvent): + implements(interfaces.IOrderProcessedEvent) + +class OrderCreatedEvent(OrderEvent): + implements(interfaces.IOrderCreatedEvent) + +class OrderAboutToBeRecreatedEvent(OrderEvent): + implements(interfaces.IOrderAboutToBeRecreatedEvent) + +class OrderRecreatedEvent(OrderEvent): + implements(interfaces.IOrderRecreatedEvent) + +class OrderRecoveredEvent(OrderEvent): + implements(interfaces.IOrderRecoveredEvent) + +class OrderSentEvent(OrderEvent): + implements(interfaces.IOrderSentEvent) + +class OrderFailedEvent(OrderEvent): + implements(interfaces.IOrderFailedEvent) + +class OrderCanceledEvent(OrderEvent): + implements(interfaces.IOrderCanceledEvent) diff --git a/src/pcommerce/core/interfaces.py b/src/pcommerce/core/interfaces.py new file mode 100644 index 0000000..df99e2c --- /dev/null +++ b/src/pcommerce/core/interfaces.py @@ -0,0 +1,488 @@ +from zope.interface import Interface, Attribute +from zope.publisher.interfaces.browser import IBrowserView + +class IProduct(Interface): + """ A product + """ + +class IVariation(IProduct): + """ A variation of a product + """ + +class IShop(Interface): + """ shop view + """ + +class IShopFolder(Interface): + """ shop folder view + """ + +class IPrice(Interface): + """ A price + """ + +class IShoppingCart(Interface): + """ An adapter to handle a shopping cart + + the adapter supports the following stanard python methods: + + len(ShoppingCart) + ShoppingCart.has_key(key) + ShoppingCart.items() + ShoppingCart[key] + ShoppingCart[key] = value + del ShoppingCart[key] + """ + + def getProducts(): + """ returns a list of products currently in the cart + """ + + def getPrice(): + """ returns the total price of all products in the cart + """ + + def addVariation(item, amount=1): + """ adds a variation of a product to the cart + + possible values of item: + - a uid + - a list of uids (combination of multiple variations) + """ + + def add(items, amount=1): + """ adds products to the cart + + possible values of items: + - a uid + - list of uids (multiple products) + - list of dicts with 'uid' and 'amount' key (multiple products with different amounts) + """ + + def remove(items, amount=None): + """ removes products from the cart + + possible values of items: + - a uid + - list of uids (multiple products) + - list of dicts with 'uid' and 'amount' key (multiple products with different amounts) + """ + + def edit(items): + """ edits the cart + + items has to be a list of dicts with keys 'uid', 'amount' and 'remove' + """ + + def clear(): + """ clears the cart + """ + +class IOrderRegistry(Interface): + """ An adapter to handle the order registry + + the adapter supports the following standard python methods: + + len(OrderRegistry) + OrderRegistry.has_key(key) + OrderRegistry.items() + OrderRegistry[key] + OrderRegistry[key] = value + """ + + def getOrders(): + """ returns a list of orders + """ + + def getOrder(orderid): + """ returns a order by its id + """ + + def create(order): + """ generates an order from the cart + """ + + def recover(orderid): + """ recover an order from the registry + """ + + def send(orderid, lang=None): + """ sends an order + """ + + def process(orderid): + """ process an order + """ + + def cancel(orderid): + """ cancel an order + """ + + def fail(orderid): + """ fail an order + """ + +class IAddress(Interface): + """ An address + """ + + salutation = Attribute("""string""") + + name = Attribute("""string""") + + address1 = Attribute("""string""") + + address2 = Attribute("""string""") + + zip = Attribute("""string""") + + city = Attribute("""string""") + + country = Attribute("""string""") + + zone = Attribute("""string""") + + email = Attribute("""string""") + + phone = Attribute("""string""") + + def mailInfo(request, lang=None, customer=False): + """ returns plain text information about the address to be sent by email """ + +class IAddressFactory(Interface): + """ An adapter to validate and create IAddress objects + """ + + def create(tag): + """ Returns a new Address object based on the request + """ + + def validate(tag): + """ Validates the data in the request to match the ones used for an Address + """ + +class IOrder(Interface): + """ An order + """ + + state = Attribute( + """integer: the current state of the order""") + + orderid = Attribute( + """string: the orderid""") + + userid = Attribute( + """string: the userid""") + + products = Attribute( + """list: list of products""") + + date = Attribute( + """time""") + + price = Attribute( + """float: the price""") + + zone = Attribute( + """tuple: (name, (tax, taxname))""") + + currency = Attribute( + """string: the currency""") + + address = Attribute( + """IAddress: customer address""") + + paymentid = Attribute( + """string: name of the payment method""") + + paymentdata = Attribute( + """IPayment: data stored by the payment method""") + + shipmentids = Attribute( + """dict: mapping of shipmentid to product uids""") + + shipmentdata = Attribute( + """dict: mapping of IShipmentData objects to shipmentid""") + + pretaxcharges = Attribute( + """tuple: list of IChargeData objects""") + + posttaxcharges = Attribute( + """tuple: list of IChargeData objects""") + + total = Attribute( + """float: the total price including tax and pre tax shipment prices""") + + subtotal = Attribute( + """float: the total price including pre tax shipment prices""") + + totalincl = Attribute( + """float: the total price including tax and shipment prices""") + + pretaxcharge = Attribute( + """float: pre tax charge""") + + posttaxcharge = Attribute( + """float: post tax charge""") + + zonename = Attribute( + """string: the name of the zone""") + + taxname = Attribute( + """string: the name of the tax""") + + tax = Attribute( + """float: the tax factor""") + + pricetax = Attribute( + """float: the tax price""") + +class IPaymentProcessor(Interface): + """""" + + def processOrder(orderid, paymentid, lang=None): + """ Processes an order """ + +class IOrderEvent(Interface): + """ An event that's fired upon order change. + """ + registry = Attribute(u'The order registry the order is stored in') + order = Attribute(u'The order object') + +class IOrderProcessingSuccessfulEvent(IOrderEvent): + """ An event that's fired if processing an order was successful + """ + +class IOrderProcessingFailedEvent(IOrderEvent): + """ An event that's fired if processing an order failed + """ + +class IOrderProcessedEvent(IOrderEvent): + """ An event fired after a order has been processed + """ + +class IOrderCreatedEvent(IOrderEvent): + """ An event that's fired if an order was created from a cart + """ + +class IOrderAboutToBeRecreatedEvent(IOrderEvent): + """ An event that's fired if an order is about to be recreated from a cart + """ + +class IOrderRecreatedEvent(IOrderEvent): + """ An event that's fired if an order was re created from a cart + """ + +class IOrderRecoveredEvent(IOrderEvent): + """ An event that's fired if an order was recovered + """ + +class IOrderSentEvent(IOrderEvent): + """ An event that's fired if an order was sent + """ + +class IOrderFailedEvent(IOrderEvent): + """ An event that's fired if an order failed + """ + +class IOrderCanceledEvent(IOrderEvent): + """ An event that's fired if an order was canceled + """ + +class IPricing(Interface): + """ An adapter to handle prices of a product + """ + + def getPrice(): + """ The lowest available price + """ + + def getBasePrice(): + """ The base price defined on the product + """ + +class IImaging(Interface): + """ An adapter to handle images of a product + """ + + def getImages(): + """ All Images inside of the Product + """ + +class ITaxes(Interface): + """ An adapter to handle taxes based on zones + + len(Taxes) + Taxes.has_key(key) + Taxes.items() + Taxes[key] + Taxes[key] = value + del Taxes[key] + """ + + def edit(taxes): + """ edits the taxes + + taxes has to be a list of dicts with keys 'zone', 'tax', 'taxname' + """ + +class ICheckoutView(Interface): + """ Checkout view + """ + +class ISteps(Interface): + """ Steps provider + """ + +class IRequiredComponents(Interface): + """ Required components provider + + Components which have to be processed in order to + make an order definite + """ + +class IComponent(IBrowserView): + """ A component for the checkout steps + """ + + dependencies = Attribute(u'Tuple: name of dependencies components') + + def validate(self): + """ validate the form values """ + + def process(self): + """ process of the component """ + + def renders(self): + """ defines whether a component renders or not """ + +class IPaymentRegistry(Interface): + """ An adapter holding registered payment + """ + + def getPayments(): + """ get all registered payment methods """ + +class IShipmentRegistry(Interface): + """ An adapter holding registered shipments + """ + + def getShipments(): + """ get all registered shipment methods """ + +class IPaymentMethod(Interface): + """ A payment method + """ + + title = Attribute( + """unicode: the title of the payment method""") + + decription = Attribute( + """unicode: the description of the payment method""") + + icon = Attribute( + """string: icon resource""") + + logo = Attribute( + """string: logo resource""") + + def verifyPayment(order): + """verify the payment""" + + def mailInfo(order, lang=None, customer=False): + """ returns plain text information about the payment to be sent by email """ + +class IPaymentData(Interface): + """ A payment object to be stored on the order + """ + + paymentid = Attribute( + """ the name of the corresponding payment method """) + + pretaxcharge = Attribute( + """ returns the pre tax charge for this payment """) + + posttaxcharge = Attribute( + """ returns the post tax charge for this payment """) + +class IPaymentView(Interface): + """ A payment view + """ + + def validate(self): + """ validate the form values """ + + def process(self): + """ process of the payment view and return a IPaymentData object """ + + def renders(self): + """ defines whether a payment view renders or not """ + +class IShipmentMethod(Interface): + """ A shipment method + """ + + title = Attribute( + """unicode: the title of the payment method""") + + decription = Attribute( + """unicode: the description of the payment method""") + + icon = Attribute( + """string: icon resource""") + + logo = Attribute( + """string: logo resource""") + + def mailInfo(order, lang=None, customer=False): + """ returns plain text information about the shipment to be sent by email """ + +class IShipmentData(Interface): + """ A shipment object to be stored on the order + """ + + shipmentid = Attribute( + """ the name of the corresponding shipment method """) + + pretaxcharge = Attribute( + """ returns the pre tax charge for this shipment """) + + posttaxcharge = Attribute( + """ returns the post tax charge for this shipment """) + +class IShipmentView(Interface): + """ A shipment view + """ + + def validate(self): + """ validate the form values """ + + def process(self): + """ process of the shipment view and return a IShipmentData object """ + + def renders(self): + """ defines whether a shipment view renders or not """ + +class IPreTaxCharge(Interface): + """ An adapter to provide a pre tax charge + """ + + def process(order): + """ returns an IChargeData object containing the charge """ + +class IPostTaxCharge(Interface): + """ An adapter to provide a post tax charge + """ + + def process(order): + """ returns an IChargeData object containing the charge """ + +class IChargeData(Interface): + """ An additional charge for an order + """ + + title = Attribute( + """unicode: the title of the charge""") + + price = Attribute( + """flaot: the price""") diff --git a/src/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po b/src/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po new file mode 100644 index 0000000..53517b4 --- /dev/null +++ b/src/pcommerce/core/locales/de/LC_MESSAGES/pcommerce.po @@ -0,0 +1,770 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: 2007-11-01 10:18+0100\n" +"Last-Translator: Simon Kaeser \n" +"Language-Team: Deutsch \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: pcommerce\n" +"Language-code: de\n" +"Language-name: Deutsch\n" +"Preferred-encodings: utf-8 latin1\n" +"X-is-fallback-for: de-ch de-de de-at de-li de-lu\n" +"X-Poedit-Language: German\n" +"X-Poedit-Country: GERMANY\n" +"X-Poedit-SourceCharset: utf-8\n" + +#. Default: "Add image" +#: browser/images.pt:23 +msgid "Add image" +msgstr "Bild hinzufügen" + +#. Default: "Add price" +#: browser/prices.pt:24 +msgid "Add price" +msgstr "Preis hinzufügen" + +#. Default: "Add variation" +#: browser/variations.pt:22 +msgid "Add variation" +msgstr "Variation hinzufügen" + +#: browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "${count} Artikel dem Warenkorb hinzugefügt" + +#: browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "Artikel dem Warenkorb hinzugefügt" + +#: content/variation.py:35 +msgid "Additional price" +msgstr "Preisaufschlag" + +#. Default: "Additional prices" +#: browser/prices.pt:27 +msgid "Additional prices" +msgstr "Zusätzliche Preise" + +#: steps.py:10 +msgid "Address" +msgstr "Adresse" + +#. Default: "Address 1" +#: browser/address.pt:139 +msgid "Address 1" +msgstr "Adresse 1" + +#. Default: "Address 2" +#: browser/address.pt:166 +msgid "Address 2" +msgstr "Adresse 2" + +#. Default: "Amount" +#: browser/cart.pt:42 +msgid "Amount" +msgstr "Anzahl" + +#. Default: "Billing address" +#: browser/components/address.pt:12 +msgid "Billing address" +msgstr "Rechnungsadresse" + +#: browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "Bestellung abbrechen" + +#. Default: "Check out" +#: browser/cart.pt:34 +msgid "Check out" +msgstr "zur Kasse gehen" + +#. Default: "Company" +#: browser/address.pt:120 +msgid "Company" +msgstr "Firma" + +#. Default: "Confirmation" +#: browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "Bestätigung" + +#: browser/checkout.py:255 +msgid "Continue shopping" +msgstr "Einkauf fortsetzen" + +#. Default: "Country" +#: browser/address.pt:224 +msgid "Country" +msgstr "Land" + +#. Default: "Edit cart" +#: browser/cart.pt:120 +msgid "Edit cart" +msgstr "Warenkorb bearbeiten" + +#. Default: "Email" +#: browser/address.pt:294 +msgid "Email" +msgstr "Email" + +#. Default: "Email address" +#: browser/configlet.pt:116 +msgid "Email address" +msgstr "Emailadresse" + +#. Default: "First name" +#: browser/address.pt:64 +msgid "First name" +msgstr "Vorname" + +#. Default: "GTC" +#: browser/configlet.pt:68 +msgid "GTC" +msgstr "AGB" + +#: content/product.py:59 +msgid "Hot product" +msgstr "Hot Produkt" + +#. Default: "I accept the ${link}" +#: browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "Ich akzeptiere die ${link}" + +#. Default: "Image" +#: browser/images.pt:63 +msgid "Image" +msgstr "Bild" + +#. Default: "Images" +#: browser/images.pt:26 +msgid "Images" +msgstr "Bilder" + +#. Default: "Last name" +#: browser/address.pt:92 +msgid "Last name" +msgstr "Nachname" + +#. Default: "Manage orders" +#: profiles/default/actions.xml +msgid "Manage orders" +msgstr "Bestellungen verwalten" + +#. Default: "Mr." +#: browser/address.pt:46 +msgid "Mr." +msgstr "Herr" + +#. Default: "Mrs. / Ms." +#: browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "Frau" + +#: content/product.py:51 +msgid "New product" +msgstr "Neues Produkt" + +#. Default: "New products in our shop" +#: browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "Neue Produkte im Shop" + +#: browser/checkout.py:258 +msgid "Next step" +msgstr "Nächster Schritt" + +#: browser/orders.py:110 +msgid "No" +msgstr "Artikelnummer" + +#. Default: "No of articles:" +#: browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "Anzahl Artikel:" + +#. Default: "Overview" +#: browser/components/overview.pt:9 +msgid "Overview" +msgstr "Übersicht" + +#. Default: "PCommerce configuration" +#: browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "Einstellungen PCommerce" + +#. Default: "Payment" +#: browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "Zahlungsart" + +#: browser/checkout.py:331 +msgid "Payment canceled" +msgstr "Zahlungsvorgang abgebrochen" + +#: browser/checkout.py:316 +msgid "Payment failed" +msgstr "Zahlungsvorgang fehlgeschlagen" + +#. Default: "Phone" +#: browser/address.pt:322 +msgid "Phone" +msgstr "Telefon" + +#: browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "Bitte geben Sie eine Dezimalzahl ein (z.B. 7.6)" + +#: browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "Bitte geben Sie einen Namen für di Steuer ein" + +#: browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "Bitte geben Sie einen Zonennamen an" + +#: browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "Bitte wählen Sie eine Zahlungsmethode" + +#: browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "Bitte wählen Sie eine Lieferart" + +#: browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "Bitte wählen Sie eine Variation aus" + +#: browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "Bitte geben Sie eine Anzahl an" + +#. Default: "Post checkout" +#: browser/configlet.pt:92 +msgid "Post checkout" +msgstr "Nach dem Bestellvorgang" + +#: browser/checkout.py:247 +msgid "Previous step" +msgstr "Vorhergehender Schritt" + +#. Default: "Price" +#: browser/cart.pt:43 +msgid "Price" +msgstr "Preis" + +#. Default: "Price total" +#: browser/cart.pt:44 +msgid "Price total" +msgstr "Gesamtpreis" + +#: browser/checkout.py:246 +msgid "Print" +msgstr "Drucken" + +#. Default: "Product" +#: browser/cart.pt:41 +msgid "Product" +msgstr "Produkt" + +#. Default: "Product highlights" +#: browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "Produkte-Highlights" + +#. Default: "Product variations" +#: browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "Produktvariationen" + +#. Default: "Productname" +#: browser/configlet.pt:36 +msgid "Productname" +msgstr "Produktname" + +#. Default: "Related products" +#: browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "Verwandte Produkte" + +#. Default: "Remove" +#: browser/cart.pt:45 +msgid "Remove" +msgstr "Entfernen" + +#: browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "${count} Artikel vom Warenkorb entfernt" + +#: browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "Artikel vom Warenkorb entfernt" + +#. Default: "Salutation" +#: browser/address.pt:35 +msgid "Salutation" +msgstr "Anrede" + +#. Default: "Select the desired payment method" +#: browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "Wählen Sie die gewünschte Zahlungsmethode" + +#. Default: "Select the desired shipment method" +#: browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "Wählen Sie die gewünschte Lieferart" + +#. Default: "Select the desired shipment method for the following products:" +#: browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "Wählen Sie die gewünschte Lieferart für folgende Produkte:" + +#: browser/checkout.py:257 +msgid "Send order" +msgstr "Bestellung absenden" + +#. Default: "Shipment" +#: browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "Lieferung" + +#: browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "Warenkorb" + +#. Default: "Tax factor" +#: browser/configlet.pt:145 +msgid "Tax factor" +msgstr "Steuerfaktor" + +#. Default: "Tax included in product price" +#: browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "Steuer im Produktpreis inbegriffen" + +#. Default: "Tax name" +#: browser/configlet.pt:144 +msgid "Tax name" +msgstr "Steuername" + +#. Default: "Taxes" +#: browser/configlet.pt:138 +msgid "Taxes" +msgstr "Steuern" + +#. Default: "Thank you!" +#: browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "Vielen Dank!" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "Die Emailadresse welche Emails von PCommerce empfängt und versendet" + +#: browser/components/gtc.py:17 +msgid "" +"The general terms and conditions have to be accepted to finish your check " +"out." +msgstr "" +"Die Allgemeinen Geschäftsbedingungen müssen akzeptiert werden, bevor der " +"Bestellvorgang abgeschlossen werden kann." + +#. Default: "The name appearing in payment-terminals" +#: browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "Der Name, der in den Zahlungsmasken angezeigt wird" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: browser/configlet.pt:73 +msgid "" +"The path to the page holding the general terms and conditions to accept " +"before payment" +msgstr "" +"Der Pfad zu jener Seite, welche die Allgemeinen Geschäftsbedingungen " +"enthält, die vor der Zahlung akzeptiert werden müssen" + +#. Default: "The path to the page to be redirected to after checkout" +#: browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "" +"Der Pfad zu jener Seite, auf welche nach Abschluss des Bestellvorgangs " +"weitergeleitet werden soll." + +#. Default: "Total" +#: browser/cart.pt:78 +msgid "Total" +msgstr "Total" + +#. Default: "Total ${currency}:" +#: browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "Total ${currency}:" + +#. Default: "Total incl. ${taxname}" +#: browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "Total inkl. ${taxname}:" + +#: order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "Total inkl. ${tax}% ${taxname}" + +#. Default: "Total incl. charges" +#: browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "Total inkl. Gebühren" + +#. Default: "Total incl. charges and ${taxname}" +#: browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "Total inkl. Gebühren und ${taxname}" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "Total inkl. Gebühren und ${tax}% ${taxname}" + +#: content/variation.py:26 +msgid "Type" +msgstr "Typ" + +#. Default: "Variations" +#: browser/variations.pt:25 +msgid "Variations" +msgstr "Variationen" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: browser/components/confirmation.pt:12 +msgid "" +"We successfully received your order. An Email has been sent to you " +"containing all the order details." +msgstr "" +"Wir haben Ihre Bestellung erfolgreich erhalten. Ein Email mit allen " +"Informationen zu Ihrer Bestellung wurde an Sie versandt." + +#: browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "Sie haben noch keine Produkte in Ihrem Warenkorb" + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: browser/cart.pt:108 +msgid "" +"You have to be registered to check out your order, either ${log_in} if you " +"already have an account or head over to the ${registration_form} if you " +"don't." +msgstr "" +"Sie müssen angemeldet sein, um zur Kasse zu gehen; ${log_in}, falls Sie " +"bereits einen Benutzer haben oder füllen Sie das ${registration_form} aus " +"falls nicht." + +#. Default: "Your shopping cart" +#: browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "Ihr Warenkorb" + +#. Default: "Your shopping cart is empty" +#: browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "Ihr Warenkorb ist leer" + +#. Default: "ZIP / City" +#: browser/address.pt:185 +msgid "ZIP / City" +msgstr "PLZ / Ort" + +#. Default: "Zone" +#: browser/address.pt:253 +msgid "Zone" +msgstr "Zone" + +#. Default: "add" +#: browser/configlet.pt:192 +msgid "add" +msgstr "hinzufügen" + +#. Default: "add to cart" +#: browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "zum Warenkorb hinzufügen" + +#. Default: "Check out" +#: browser/checkout.pt:15 +msgid "checkout_title" +msgstr "Kasse" + +#. Default: "List of all orders and their statuses" +#: profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "Liste aller Bestellungen mit entsprechendem Status" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: browser/images.pt:40 +msgid "description_no_images" +msgstr "" +"Dieses Produkt hat keine weiteren Bilder. Um ein Bild hinzuzufügen, klicken " +"Sie den Knopf 'hinzufügen' oder fügen Sie Inhalte aus einem anderen Produkt " +"ein." + +#. Default: "No orders were found." +#: browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "Es wurden keine Bestellungen gefunden." + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" +"Dieses Produkt hat keine zusätzlichen Preise. Um einen Preis hinzuzufügen, " +"klicken Sie den Knopf 'Hinzufügen' oder fügen Sie Inhalte aus einem anderen " +"Produkt ein." + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: content/variation.py:52 +msgid "description_price" +msgstr "" +"Wenn mehrere Variationen aus verschiedenen Kategorien einen Einzelpreis " +"besitzen, wird bei der Preisfindung der Kombination der grössere Preis " +"gewählt." + +#. Default: "Shipment methods for this product" +#: content/product.py:68 +msgid "description_shipment_methods" +msgstr "Versandmöglichkeiten für dieses Produkt" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: order.py:475 +msgid "email_customer_body" +msgstr "" +"Sehr geehrte/r ${name}\n" +"\n" +"Ihre Bestellung wurde erfolgreich registriert. Nachfolgend finden Sie\n" +"eine komplette Übersicht Ihrer Bestellung.\n" +"\n" +"Bestellnummer: ${orderid}\n" +"\n" +"${cart}\n" +"Währung: ${currency}\n" +"\n" +"\n" +"Adresse:\n" +"${address}\n" +"\n" +"Zahlung:\n" +"${payment}\n" +"\n" +"Lieferung:\n" +"${shipments}\n" +"\n" +"\n" +"Falls Sie Fragen betreffend Ihrer Bestellung haben, zögern Sie nicht uns " +"unter\n" +"${from_email} zu kontaktieren.\n" +"\n" +"Freundliche Grüsse\n" +"\n" +"${from_name}" + +#. Default: "Confirmation e-mail" +#: order.py:402 +msgid "email_customer_title" +msgstr "Bestellungsbestätigung" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: order.py:454 +msgid "email_order_body" +msgstr "" +"Neue Bestellung von ${name}\n" +"\n" +"Bestellnummer: ${orderid}\n" +"\n" +"${cart}\n" +"Währung: ${currency}\n" +"\n" +"\n" +"Addresse:\n" +"${address}\n" +"\n" +"Zahlung:\n" +"${payment}\n" +"\n" +"Lieferung:\n" +"${shipments}" + +#. Default: "New order [${orderid}]" +#: order.py:393 +msgid "email_order_title" +msgstr "Neue Bestellung [${orderid}]" + +#. Default: "general terms and conditions" +#: browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "Allgemeinen Geschäftsbedingungen" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: browser/images.pt:35 +msgid "info_Image" +msgstr "" +"Sie befinden sich momentan auf der Bilderansicht einer Variation des " +"Produkts ${product}." + +#. Default: "You are currently looking at a variation of the product ${product}." +#: browser/variation.pt:25 +msgid "info_variation" +msgstr "" +"Sie befinden sich momentan auf einer Variation des Produkts ${product}." + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "" +"Sie befinden sich momentan auf der Preisansicht einer Variation des Produkts " +"${product}." + +#. Default: "Address" +#: browser/orders.py:73 +msgid "label_address" +msgstr "Adresse" + +#. Default: "Cancelled" +#: browser/orders.py:37 +msgid "label_cancelled" +msgstr "Abgebrochen" + +#. Default: "Currency" +#: browser/orders.py:59 +msgid "label_currency" +msgstr "Währung" + +#. Default: "Date" +#: browser/orders.py:56 +msgid "label_date" +msgstr "Datum" + +#. Default: "Failed" +#: browser/orders.py:36 +msgid "label_failed" +msgstr "Fehlgeschlagen" + +#. Default: "Initialized" +#: browser/orders.py:33 +msgid "label_initialized" +msgstr "Ausgelöst" + +#. Default: "Order id" +#: browser/orders.py:50 +msgid "label_order_id" +msgstr "Bestellnummer" + +#. Default: "Order status" +#: browser/orders.py:66 +msgid "label_order_state" +msgstr "Bestellstatus" + +#. Default: "Price total" +#: browser/orders.py:62 +msgid "label_price_total" +msgstr "Gesamtpreis" + +#. Default: "Processed" +#: browser/orders.py:35 +msgid "label_processed" +msgstr "Verarbeitet" + +#. Default: "Products" +#: browser/orders.py:77 +msgid "label_products" +msgstr "Produkte" + +#. Default: "Sent" +#: browser/orders.py:34 +msgid "label_sent" +msgstr "Gesendet" + +#. Default: "Shipment methods" +#: content/product.py:67 +msgid "label_shipment_methods" +msgstr "Versandarten" + +#. Default: "Shipment id's" +#: browser/orders.py:81 +msgid "label_shipmentids" +msgstr "Versandarten IDs" + +#. Default: "User id" +#: browser/orders.py:53 +msgid "label_user_id" +msgstr "Benutzername" + +#. Default: "Zone" +#: browser/orders.py:69 +msgid "label_zone" +msgstr "Zone" + +#. Default: "log in" +#: browser/cart.pt:101 +msgid "log_in" +msgstr "melden Sie sich an" + +#. Default: "Check out canceled" +#: browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "Bestellung abgebrochen" + +#. Default: "Check out failed" +#: browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "Bestellung fehlgeschlagen" + +#. Default: "${offer} instead of ${price}" +#: browser/macros.pt:11 +msgid "price_offer" +msgstr "${offer} statt ${price}" + +#. Default: "registration form" +#: browser/cart.pt:108 +msgid "registration_form" +msgstr "Registrierungsformular" + +#. Default: "remove" +#: browser/configlet.pt:168 +msgid "remove" +msgstr "löschen" + +#. Default: "Please supply an order id." +#: browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "Bitte geben Sie eine Bestellnummer ein." + +#. Default: "Please check the order id." +#: browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "Bitte überprüfen Sie die Bestellnummer." + +#. Default: "Manage orders" +#: browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "Bestellungen verwalten" + +#. Default: "Which one?" +#: browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "Welche?" + +#. Default: "Order details" +#: browser/order_details.pt:17 +msgid "title_order_details" +msgstr "Informationen zur Bestellung" + +#. Default: "The order could not be found." +#: browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "Die Bestellung konnte nicht gefunden werden." diff --git a/src/pcommerce/core/locales/de/LC_MESSAGES/plone.po b/src/pcommerce/core/locales/de/LC_MESSAGES/plone.po new file mode 100644 index 0000000..fdd04af --- /dev/null +++ b/src/pcommerce/core/locales/de/LC_MESSAGES/plone.po @@ -0,0 +1,54 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2008-04-07 14:15-100\n" +"Last-Translator: Simon Kaeser \n" +"Language-code: de\n" +"Language-name: Deutsch\n" +"Preferred-encodings: utf-8 latin1\n" +"Domain: plone\n" +"X-is-fallback-for: de-ch de-de de-at de-li de-lu\n" +"Project-Id-Version: pcommerce.core\n" +"PO-Revision-Date: 2007-11-01 10:18+0100\n" +"Language-Team: Simon Kaeser \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: German\n" +"X-Poedit-Country: GERMANY\n" +"X-Poedit-SourceCharset: utf-8\n" + +msgid "Price" +msgstr "Preis" + +msgid "A price" +msgstr "Ein Preis" + +msgid "Product" +msgstr "Produkt" + +msgid "A product" +msgstr "Ein Produkt" + +msgid "Variation" +msgstr "Variation" + +msgid "A variation of a product" +msgstr "Eine Variation eines Produkts" + +msgid "Variations" +msgstr "Variationen" + +msgid "Prices" +msgstr "Preise" + +msgid "PCommerce configuration" +msgstr "PCommerce Einstellungen" + +msgid "Shop" +msgstr "Shop" + +msgid "ShopFolder" +msgstr "Shopordner" + +msgid "Images" +msgstr "Bilder" diff --git a/src/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po b/src/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po new file mode 100644 index 0000000..b409dad --- /dev/null +++ b/src/pcommerce/core/locales/es/LC_MESSAGES/pcommerce.po @@ -0,0 +1,771 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: 2011-09-05 08:59+0100\n" +"Last-Translator: Manuel Gualda Caballero \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: en\n" +"Language-Name: English\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: pcommerce\n" +"Language-code: es\n" +"Language-name: Spanish\n" +"Preferred-encodings: utf-8 latin1\n" +"X-is-fallback-for: es-es es-ar es-bo es-cl es-co es-cr es-do es-ec es-sv es-" +"gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n" +"X-Poedit-Language: Spanish\n" +"X-Poedit-Country: SPAIN\n" +"X-Poedit-SourceCharset: utf-8\n" + +#. Default: "Add image" +#: browser/images.pt:23 +msgid "Add image" +msgstr "Añadir imagen" + +#. Default: "Add price" +#: browser/prices.pt:24 +msgid "Add price" +msgstr "Añadir precio" + +#. Default: "Add variation" +#: browser/variations.pt:22 +msgid "Add variation" +msgstr "Añadir variación" + +#: browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "Se han añadido ${count} productos al carrito" + +#: browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "Producto añadido al carrito" + +#: content/variation.py:35 +msgid "Additional price" +msgstr "Precio adicional" + +#. Default: "Additional prices" +#: browser/prices.pt:27 +msgid "Additional prices" +msgstr "Precios adicionales" + +#: steps.py:10 +msgid "Address" +msgstr "Dirección" + +#. Default: "Address 1" +#: browser/address.pt:139 +msgid "Address 1" +msgstr "Dirección (1)" + +#. Default: "Address 2" +#: browser/address.pt:166 +msgid "Address 2" +msgstr "Dirección (2)" + +#. Default: "Amount" +#: browser/cart.pt:42 +msgid "Amount" +msgstr "Cantidad" + +#. Default: "Billing address" +#: browser/components/address.pt:12 +msgid "Billing address" +msgstr "Dirección de facturación" + +#: browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "Cancelar pedido" + +#. Default: "Check out" +#: browser/cart.pt:34 +msgid "Check out" +msgstr "Realizar pedido" + +#. Default: "Company" +#: browser/address.pt:120 +msgid "Company" +msgstr "Empresa y CIF" + +#. Default: "Confirmation" +#: browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "Confirmación del pedido" + +#: browser/checkout.py:255 +msgid "Continue shopping" +msgstr "Continuar comprando" + +#. Default: "Country" +#: browser/address.pt:224 +msgid "Country" +msgstr "País" + +#. Default: "Edit cart" +#: browser/cart.pt:120 +msgid "Edit cart" +msgstr "Modificar el carrito" + +#. Default: "Email" +#: browser/address.pt:294 +msgid "Email" +msgstr "Correo" + +#. Default: "Email address" +#: browser/configlet.pt:116 +#, fuzzy +msgid "Email address" +msgstr "Dirección de facturación" + +#. Default: "First name" +#: browser/address.pt:64 +msgid "First name" +msgstr "Nombre" + +#. Default: "GTC" +#: browser/configlet.pt:68 +msgid "GTC" +msgstr "CGC" + +#: content/product.py:59 +msgid "Hot product" +msgstr "Producto popular" + +#. Default: "I accept the ${link}" +#: browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "Acepto las ${link}" + +#. Default: "Image" +#: browser/images.pt:63 +msgid "Image" +msgstr "Imagen" + +#. Default: "Images" +#: browser/images.pt:26 +msgid "Images" +msgstr "Imágenes" + +#. Default: "Last name" +#: browser/address.pt:92 +msgid "Last name" +msgstr "Apellidos" + +#. Default: "Manage orders" +#: profiles/default/actions.xml +msgid "Manage orders" +msgstr "Administrar pedidos" + +#. Default: "Mr." +#: browser/address.pt:46 +msgid "Mr." +msgstr "Don" + +#. Default: "Mrs. / Ms." +#: browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "Doña" + +#: content/product.py:51 +msgid "New product" +msgstr "Nuevo producto" + +#. Default: "New products in our shop" +#: browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "Nuevos productos" + +#: browser/checkout.py:258 +msgid "Next step" +msgstr "Siguiente paso" + +#: browser/orders.py:110 +msgid "No" +msgstr "Nº" + +#. Default: "No of articles:" +#: browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "Nº de productos:" + +#. Default: "Overview" +#: browser/components/overview.pt:9 +msgid "Overview" +msgstr "Vista general" + +#. Default: "PCommerce configuration" +#: browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "Configuración de PCommerce" + +#. Default: "Payment" +#: browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "Pago" + +#: browser/checkout.py:331 +msgid "Payment canceled" +msgstr "Pago cancelado" + +#: browser/checkout.py:316 +msgid "Payment failed" +msgstr "Error en el pago" + +#. Default: "Phone" +#: browser/address.pt:322 +msgid "Phone" +msgstr "Teléfono" + +#: browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "" +"Por favor, introduzca un número con los decimales marcados con punto (ej.: " +"7.6)" + +#: browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "Por favor, indique un nombre de impuesto" + +#: browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "Por favor, indique un nombre de zona" + +#: browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "Por favor, seleccione un método de pago" + +#: browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "Por favor, seleccione un método de envío" + +#: browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "Por favor, seleccione una variación" + +#: browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "Por favor, especifique una cantidad" + +#. Default: "Post checkout" +#: browser/configlet.pt:92 +msgid "Post checkout" +msgstr "Tras el pedido" + +#: browser/checkout.py:247 +msgid "Previous step" +msgstr "Paso anterior" + +#. Default: "Price" +#: browser/cart.pt:43 +msgid "Price" +msgstr "Precio" + +#. Default: "Price total" +#: browser/cart.pt:44 +msgid "Price total" +msgstr "Precio total" + +#: browser/checkout.py:246 +msgid "Print" +msgstr "Imprimir" + +#. Default: "Product" +#: browser/cart.pt:41 +msgid "Product" +msgstr "Producto" + +#. Default: "Product highlights" +#: browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "Productos destacados" + +#. Default: "Product variations" +#: browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "Variaciones del producto" + +#. Default: "Productname" +#: browser/configlet.pt:36 +msgid "Productname" +msgstr "Nombre del producto" + +#. Default: "Related products" +#: browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "Productos relacionados" + +#. Default: "Remove" +#: browser/cart.pt:45 +msgid "Remove" +msgstr "Eliminar" + +#: browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "Se han eliminado ${count} productos del carrito" + +#: browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "Producto eliminado del carrito" + +#. Default: "Salutation" +#: browser/address.pt:35 +msgid "Salutation" +msgstr "Tratamiento" + +#. Default: "Select the desired payment method" +#: browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "Seleccione el método de pago deseado" + +#. Default: "Select the desired shipment method" +#: browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "Seleccione el método de envío deseado" + +#. Default: "Select the desired shipment method for the following products:" +#: browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "Seleccione el método de envío deseado para los siguientes productos:" + +#: browser/checkout.py:257 +msgid "Send order" +msgstr "Realizar el pedido" + +#. Default: "Shipment" +#: browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "Envío" + +#: browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "Carrito de la compra" + +#. Default: "Tax factor" +#: browser/configlet.pt:145 +msgid "Tax factor" +msgstr "Factor del impuesto" + +#. Default: "Tax included in product price" +#: browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "Impuestos incluidos en el precio del producto" + +#. Default: "Tax name" +#: browser/configlet.pt:144 +msgid "Tax name" +msgstr "Nombre del impuesto" + +#. Default: "Taxes" +#: browser/configlet.pt:138 +msgid "Taxes" +msgstr "Impuestos" + +#. Default: "Thank you!" +#: browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "¡Gracias!" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "" + +#: browser/components/gtc.py:17 +msgid "" +"The general terms and conditions have to be accepted to finish your check " +"out." +msgstr "" +"Debe aceptar las condiciones generales de contratación para poder realizar " +"el pedido." + +#. Default: "The name appearing in payment-terminals" +#: browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "Nombre que aparecerá en los terminales de pago" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: browser/configlet.pt:73 +msgid "" +"The path to the page holding the general terms and conditions to accept " +"before payment" +msgstr "" +"Ruta hacia la página que aloja las condiciones generales de contratación que " +"hay que aceptar antes de poder realizar el pago" + +#. Default: "The path to the page to be redirected to after checkout" +#: browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "" +"Ruta hacia la página a la que se será redirigido después de realizar el " +"pedido" + +#. Default: "Total" +#: browser/cart.pt:78 +msgid "Total" +msgstr "Total" + +#. Default: "Total ${currency}:" +#: browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "Total ${currency}:" + +#. Default: "Total incl. ${taxname}" +#: browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "Total con ${taxname}:" + +#: order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "Total con ${tax}% ${taxname}" + +#. Default: "Total incl. charges" +#: browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "Total con cargos" + +#. Default: "Total incl. charges and ${taxname}" +#: browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "Total con ${taxname} y cargos" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "Total con ${tax}% ${taxname} y cargos" + +#: content/variation.py:26 +msgid "Type" +msgstr "Tipo" + +#. Default: "Variations" +#: browser/variations.pt:25 +msgid "Variations" +msgstr "Variaciones" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: browser/components/confirmation.pt:12 +msgid "" +"We successfully received your order. An Email has been sent to you " +"containing all the order details." +msgstr "" +"Hemos recibido su pedido correctamente. Se le ha enviado un correo con los " +"detalles del mismo." + +#: browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "Todavía no ha añadido ningún producto a su carrito" + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: browser/cart.pt:108 +msgid "" +"You have to be registered to check out your order, either ${log_in} if you " +"already have an account or head over to the ${registration_form} if you " +"don't." +msgstr "" +"Debe haber iniciado sesión para poder realizar su pedido: ${log_in} (si ya " +"tiene una cuenta) o ${registration_form} (si todavía no la tiene)." + +#. Default: "Your shopping cart" +#: browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "Su carrito de la compra" + +#. Default: "Your shopping cart is empty" +#: browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "Su carrito de la compra está vacío" + +#. Default: "ZIP / City" +#: browser/address.pt:185 +msgid "ZIP / City" +msgstr "CP / Localidad" + +#. Default: "Zone" +#: browser/address.pt:253 +msgid "Zone" +msgstr "Zona" + +#. Default: "add" +#: browser/configlet.pt:192 +msgid "add" +msgstr "añadir" + +#. Default: "add to cart" +#: browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "añadir al carrito" + +#. Default: "Check out" +#: browser/checkout.pt:15 +msgid "checkout_title" +msgstr "Caja" + +#. Default: "List of all orders and their statuses" +#: profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "Lista de todos los pedidos y sus estados" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: browser/images.pt:40 +msgid "description_no_images" +msgstr "" +"Este producto no tiene imágenes. Para añadir una imagen, pulse el botón de " +"añadir o pegue el contenido desde otro lugar." + +#. Default: "No orders were found." +#: browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "" +"Este producto no tiene precios adicionales. Para añadir un precio, pulse el " +"botón de añadir o pegue el contenido desde otro lugar." + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" +"Este producto no tiene precios adicionales. Para añadir un precio, pulse el " +"botón de añadir o pegue el contenido desde otro lugar." + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: content/variation.py:52 +msgid "description_price" +msgstr "" +"If multiple selected variations in different categories have unit prices, " +"the greater price will be accounted for in pricing of the selected " +"combination." + +#. Default: "Shipment methods for this product" +#: content/product.py:68 +msgid "description_shipment_methods" +msgstr "Métodos de envío para este producto" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: order.py:475 +msgid "email_customer_body" +msgstr "" +"Estimado/a ${name}\n" +"\n" +"Su pedido ha sido correctamente registrado. Vea un resumen del mismo:\n" +"\n" +"ID del pedido: ${orderid}\n" +"\n" +"${cart}\n" +"Moneda: ${currency}\n" +"\n" +"\n" +"Domicilio:\n" +"${address}\n" +"\n" +"Pago:\n" +"${payment}\n" +"\n" +"Envío:\n" +"${shipments}\n" +"\n" +"\n" +"Si tiene alguna pregunta sobre su compra, no dude en escribirnos a " +"${from_email}.\n" +"\n" +"Atentamente,\n" +"\n" +"${from_name}" + +#. Default: "Confirmation e-mail" +#: order.py:402 +msgid "email_customer_title" +msgstr "Confirmación de su pedido" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: order.py:454 +msgid "email_order_body" +msgstr "" +"Nuevo pedido realizado por ${name}\n" +"\n" +"ID del pedido: ${orderid}\n" +"\n" +"${cart}\n" +"Moneda: ${currency}\n" +"\n" +"\n" +"Dirección:\n" +"${address}\n" +"\n" +"Pago:\n" +"${payment}\n" +"\n" +"Envío:\n" +"${shipments}" + +#. Default: "New order [${orderid}]" +#: order.py:393 +msgid "email_order_title" +msgstr "Nuevo pedido [${orderid}]" + +#. Default: "general terms and conditions" +#: browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "condiciones generales de contratación" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: browser/images.pt:35 +msgid "info_Image" +msgstr "" +"Actualmente está viendo las imágenes de una variación del producto " +"${product}." + +#. Default: "You are currently looking at a variation of the product ${product}." +#: browser/variation.pt:25 +msgid "info_variation" +msgstr "Actualmente está viendo una variación del producto ${product}." + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "" +"Actualmente está viendo los precios de una variación del producto ${product}." + +#. Default: "Address" +#: browser/orders.py:73 +msgid "label_address" +msgstr "Dirección" + +#. Default: "Cancelled" +#: browser/orders.py:37 +msgid "label_cancelled" +msgstr "Cancelado" + +#. Default: "Currency" +#: browser/orders.py:59 +msgid "label_currency" +msgstr "Moneda" + +#. Default: "Date" +#: browser/orders.py:56 +msgid "label_date" +msgstr "Fecha" + +#. Default: "Failed" +#: browser/orders.py:36 +msgid "label_failed" +msgstr "Malogrado" + +#. Default: "Initialized" +#: browser/orders.py:33 +msgid "label_initialized" +msgstr "Iniciado" + +#. Default: "Order id" +#: browser/orders.py:50 +msgid "label_order_id" +msgstr "ID del pedido" + +#. Default: "Order status" +#: browser/orders.py:66 +msgid "label_order_state" +msgstr "Estado del pedido" + +#. Default: "Price total" +#: browser/orders.py:62 +msgid "label_price_total" +msgstr "Precio total" + +#. Default: "Processed" +#: browser/orders.py:35 +msgid "label_processed" +msgstr "Procesado" + +#. Default: "Products" +#: browser/orders.py:77 +msgid "label_products" +msgstr "Productos" + +#. Default: "Sent" +#: browser/orders.py:34 +msgid "label_sent" +msgstr "Enviar" + +#. Default: "Shipment methods" +#: content/product.py:67 +msgid "label_shipment_methods" +msgstr "Métodos de envío" + +#. Default: "Shipment id's" +#: browser/orders.py:81 +msgid "label_shipmentids" +msgstr "ID de los envíos" + +#. Default: "User id" +#: browser/orders.py:53 +msgid "label_user_id" +msgstr "ID del usuario" + +#. Default: "Zone" +#: browser/orders.py:69 +msgid "label_zone" +msgstr "Zona" + +#. Default: "log in" +#: browser/cart.pt:101 +msgid "log_in" +msgstr "iniciar sesión" + +#. Default: "Check out canceled" +#: browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "Pedido cancelado" + +#. Default: "Check out failed" +#: browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "Error en el pedido" + +#. Default: "${offer} instead of ${price}" +#: browser/macros.pt:11 +msgid "price_offer" +msgstr "${offer} en lugar de ${price}" + +#. Default: "registration form" +#: browser/cart.pt:108 +msgid "registration_form" +msgstr "formulario de registro" + +#. Default: "remove" +#: browser/configlet.pt:168 +msgid "remove" +msgstr "eliminar" + +#. Default: "Please supply an order id." +#: browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "Por favor, facilite un número (ID) de pedido." + +#. Default: "Please check the order id." +#: browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "Por favor, compruebe el número (ID) de pedido." + +#. Default: "Manage orders" +#: browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "Administrar pedidos" + +#. Default: "Which one?" +#: browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "¿Cuál?" + +#. Default: "Order details" +#: browser/order_details.pt:17 +msgid "title_order_details" +msgstr "Detalles del pedido" + +#. Default: "The order could not be found." +#: browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "El pedido no ha podido ser encontrado." diff --git a/src/pcommerce/core/locales/es/LC_MESSAGES/plone.po b/src/pcommerce/core/locales/es/LC_MESSAGES/plone.po new file mode 100644 index 0000000..c7133d8 --- /dev/null +++ b/src/pcommerce/core/locales/es/LC_MESSAGES/plone.po @@ -0,0 +1,56 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2011-08-31 08:16+0000\n" +"PO-Revision-Date: 2011-09-04 19:32+0100\n" +"Last-Translator: Manuel Gualda Caballero \n" +"Language-Team: Spanish \n" +"Language: es\n" +"Language-code: es\n" +"Language-name: Spanish\n" +"Preferred-encodings: utf-8 latin1\n" +"Domain: plone\n" +"X-is-fallback-for: es-es es-ar es-bo es-cl es-co es-cr es-do es-ec es-sv es-gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n" +"Project-Id-Version: pcommerce.core\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Spanish\n" +"X-Poedit-Country: SPAIN\n" +"X-Poedit-SourceCharset: utf-8\n" + +msgid "Price" +msgstr "Precio" + +msgid "A price" +msgstr "Un precio" + +msgid "Product" +msgstr "Producto" + +msgid "A product" +msgstr "Un producto" + +msgid "Variation" +msgstr "Variación" + +msgid "A variation of a product" +msgstr "Una variación de un producto" + +msgid "Variations" +msgstr "Variaciones" + +msgid "Prices" +msgstr "Precios" + +msgid "PCommerce configuration" +msgstr "Configuración de PCommerce" + +msgid "Shop" +msgstr "Tienda" + +msgid "ShopFolder" +msgstr "Carpeta de tienda" + +msgid "Images" +msgstr "Imágenes" + diff --git a/src/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po b/src/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po new file mode 100755 index 0000000..e843a02 --- /dev/null +++ b/src/pcommerce/core/locales/fr/LC_MESSAGES/pcommerce.po @@ -0,0 +1,760 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: 2007-11-01 10:18+0100\n" +"Last-Translator: Steve Beyeler \n" +"Language-Team: Français \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language-code: fr\n" +"Language-name: Français\n" +"Preferred-encodings: utf-8 latin1\n" +"Domain: pcommerce\n" +"X-is-fallback-for: fr-ch fr-fr fr-be\n" +"X-Poedit-Language: Français\n" +"X-Poedit-Country: FRANCE\n" +"X-Poedit-SourceCharset: utf-8\n" + +#. Default: "Add image" +#: browser/images.pt:23 +msgid "Add image" +msgstr "Ajouter une image" + +#. Default: "Add price" +#: browser/prices.pt:24 +msgid "Add price" +msgstr "Ajouter un prix" + +#. Default: "Add variation" +#: browser/variations.pt:22 +msgid "Add variation" +msgstr "Ajouter une variation" + +#: browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "${count} articles ajoutés au panier" + +#: browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "Article ajouté au panier" + +#: content/variation.py:35 +msgid "Additional price" +msgstr "Supplément de prix" + +#. Default: "Additional prices" +#: browser/prices.pt:27 +msgid "Additional prices" +msgstr "Prix supplémentaires" + +#: steps.py:10 +msgid "Address" +msgstr "Adresse" + +#. Default: "Address 1" +#: browser/address.pt:139 +msgid "Address 1" +msgstr "Adresse 1" + +#. Default: "Address 2" +#: browser/address.pt:166 +msgid "Address 2" +msgstr "Adresse 2" + +#. Default: "Amount" +#: browser/cart.pt:42 +msgid "Amount" +msgstr "Nombre" + +#. Default: "Billing address" +#: browser/components/address.pt:12 +msgid "Billing address" +msgstr "Adresse de facturation" + +#: browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "Annuler la commande" + +#. Default: "Check out" +#: browser/cart.pt:34 +msgid "Check out" +msgstr "Passer à la caisse" + +#. Default: "Company" +#: browser/address.pt:120 +msgid "Company" +msgstr "Société" + +#. Default: "Confirmation" +#: browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "Confirmation" + +#: browser/checkout.py:255 +msgid "Continue shopping" +msgstr "Continuer les achats" + +#. Default: "Country" +#: browser/address.pt:224 +msgid "Country" +msgstr "Pays" + +#. Default: "Edit cart" +#: browser/cart.pt:120 +msgid "Edit cart" +msgstr "Editer le panier" + +#. Default: "Email" +#: browser/address.pt:294 +msgid "Email" +msgstr "Courriel" + +#. Default: "Email address" +#: browser/configlet.pt:116 +#, fuzzy +msgid "Email address" +msgstr "Adresse de facturation" + +#. Default: "First name" +#: browser/address.pt:64 +msgid "First name" +msgstr "Prénom" + +#. Default: "GTC" +#: browser/configlet.pt:68 +msgid "GTC" +msgstr "CGA" + +#: content/product.py:59 +msgid "Hot product" +msgstr "Produit TOP" + +#. Default: "I accept the ${link}" +#: browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "J'accèpte les ${link}" + +#. Default: "Image" +#: browser/images.pt:63 +msgid "Image" +msgstr "Image" + +#. Default: "Images" +#: browser/images.pt:26 +msgid "Images" +msgstr "Images" + +#. Default: "Last name" +#: browser/address.pt:92 +msgid "Last name" +msgstr "Nom" + +#. Default: "Manage orders" +#: profiles/default/actions.xml +msgid "Manage orders" +msgstr "Gérer les commandes" + +#. Default: "Mr." +#: browser/address.pt:46 +msgid "Mr." +msgstr "M." + +#. Default: "Mrs. / Ms." +#: browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "Mme" + +#: content/product.py:51 +msgid "New product" +msgstr "Nouveau produit" + +#. Default: "New products in our shop" +#: browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "Actualités dans notre shop" + +#: browser/checkout.py:258 +msgid "Next step" +msgstr "Prochaine étape" + +#: browser/orders.py:110 +msgid "No" +msgstr "Numéro d'article" + +#. Default: "No of articles:" +#: browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "Nombre d'articles:" + +#. Default: "Overview" +#: browser/components/overview.pt:9 +msgid "Overview" +msgstr "Aperçu" + +#. Default: "PCommerce configuration" +#: browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "Paramètres PCommerce" + +#. Default: "Payment" +#: browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "Mode de paiement" + +#: browser/checkout.py:331 +msgid "Payment canceled" +msgstr "Paiement annulé" + +#: browser/checkout.py:316 +msgid "Payment failed" +msgstr "Paiement échoué" + +#. Default: "Phone" +#: browser/address.pt:322 +msgid "Phone" +msgstr "Téléphone" + +#: browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "Veuillez entrer un chiffre décimal (p.ex. 7.6)" + +#: browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "Veuillez indiquer un titre pour la taxe" + +#: browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "Veuillez indiquer un titre pour la zone" + +#: browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "Veuillez choisir un mode de paiement" + +#: browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "Veuillez indiquer un type de livraison" + +#: browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "Veuillez choisir une variation" + +#: browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "Veuillez indiquer un nombre" + +#. Default: "Post checkout" +#: browser/configlet.pt:92 +msgid "Post checkout" +msgstr "Après la commande" + +#: browser/checkout.py:247 +msgid "Previous step" +msgstr "Etape précédente" + +#. Default: "Price" +#: browser/cart.pt:43 +msgid "Price" +msgstr "Prix" + +#. Default: "Price total" +#: browser/cart.pt:44 +msgid "Price total" +msgstr "Prix total" + +#: browser/checkout.py:246 +msgid "Print" +msgstr "Imprimer" + +#. Default: "Product" +#: browser/cart.pt:41 +msgid "Product" +msgstr "Produit" + +#. Default: "Product highlights" +#: browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "Produits TOP" + +#. Default: "Product variations" +#: browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "Variations du produit" + +#. Default: "Productname" +#: browser/configlet.pt:36 +msgid "Productname" +msgstr "Nom du produit" + +#. Default: "Related products" +#: browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "Produits apparentés" + +#. Default: "Remove" +#: browser/cart.pt:45 +msgid "Remove" +msgstr "Supprimer" + +#: browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "${count} articles supprimés du panier" + +#: browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "Article supprimé du panier" + +#. Default: "Salutation" +#: browser/address.pt:35 +msgid "Salutation" +msgstr "Titre" + +#. Default: "Select the desired payment method" +#: browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "Veuillez choisir le mode de paiement désiré" + +#. Default: "Select the desired shipment method" +#: browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "Veuillez choisir le type de livraison désiré" + +#. Default: "Select the desired shipment method for the following products:" +#: browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "" +"Veuillez choisir le type de livraison désiré pour les produits suivants:" + +#: browser/checkout.py:257 +msgid "Send order" +msgstr "Envoyer la commande" + +#. Default: "Shipment" +#: browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "Livraison" + +#: browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "Panier" + +#. Default: "Tax factor" +#: browser/configlet.pt:145 +msgid "Tax factor" +msgstr "Facteur taxe" + +#. Default: "Tax included in product price" +#: browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "Taxe inclue dans le prix du produit" + +#. Default: "Tax name" +#: browser/configlet.pt:144 +msgid "Tax name" +msgstr "Titre de la taxe" + +#. Default: "Taxes" +#: browser/configlet.pt:138 +msgid "Taxes" +msgstr "Taxes" + +#. Default: "Thank you!" +#: browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "Meilleurs remerciements !" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "" + +#: browser/components/gtc.py:17 +msgid "" +"The general terms and conditions have to be accepted to finish your check " +"out." +msgstr "" +"Il est nécéssaire d'accèpter les condition générales d'affaires avant de " +"compléter terminer la commande." + +#. Default: "The name appearing in payment-terminals" +#: browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "Le nom apparaissant dans les masques de paiement" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: browser/configlet.pt:73 +msgid "" +"The path to the page holding the general terms and conditions to accept " +"before payment" +msgstr "" +"Le chemin d'accès à la page contenant les conditions générales d'affaires " +"qui doivent être acceptées avant le paiement" + +#. Default: "The path to the page to be redirected to after checkout" +#: browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "Le chemin d'accès à la page à afficher une fois la commande complétée." + +#. Default: "Total" +#: browser/cart.pt:78 +msgid "Total" +msgstr "Total" + +#. Default: "Total ${currency}:" +#: browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "Total ${currency}:" + +#. Default: "Total incl. ${taxname}" +#: browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "Total ${taxname} incl.:" + +#: order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "Total ${tax}% ${taxname} incl." + +#. Default: "Total incl. charges" +#: browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "Total charges comprises" + +#. Default: "Total incl. charges and ${taxname}" +#: browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "Total charges et ${taxname} comprises" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "Total charges et ${tax}% ${taxname} comprises" + +#: content/variation.py:26 +msgid "Type" +msgstr "Type" + +#. Default: "Variations" +#: browser/variations.pt:25 +msgid "Variations" +msgstr "Variations" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: browser/components/confirmation.pt:12 +msgid "" +"We successfully received your order. An Email has been sent to you " +"containing all the order details." +msgstr "" +"Nous avons reçu votre commande avec succès. Un courriel contenant toutes les " +"information relatives à votre commande vous a été envoyé." + +#: browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "Vous n'avez pas encore placé de produits dans votre panier" + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: browser/cart.pt:108 +msgid "" +"You have to be registered to check out your order, either ${log_in} if you " +"already have an account or head over to the ${registration_form} if you " +"don't." +msgstr "" +"Il faut être connecté pour pouvoir passer à la caisse; ${log_in} si vous " +"disposez déjà d'un utilisateur, sinon veuillez remplir le " +"${registration_form} ." + +#. Default: "Your shopping cart" +#: browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "Votre panier" + +#. Default: "Your shopping cart is empty" +#: browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "Votre panier est vide" + +#. Default: "ZIP / City" +#: browser/address.pt:185 +msgid "ZIP / City" +msgstr "Code postal / Localité" + +#. Default: "Zone" +#: browser/address.pt:253 +msgid "Zone" +msgstr "Zone" + +#. Default: "add" +#: browser/configlet.pt:192 +msgid "add" +msgstr "ajouter" + +#. Default: "add to cart" +#: browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "ajouter au panier" + +#. Default: "Check out" +#: browser/checkout.pt:15 +msgid "checkout_title" +msgstr "Caisse" + +#. Default: "List of all orders and their statuses" +#: profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "Affiche toutes les commandes ainsi que leur état" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: browser/images.pt:40 +msgid "description_no_images" +msgstr "" +"Ce produit ne dispose pas davantage d'images. Pour ajouter une image " +"veuillez cliquer le bouton ajouter ou ajoutez les éléments depuis un autre " +"produit." + +#. Default: "No orders were found." +#: browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "Aucune commande n'a été trouvé." + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" +"Ce produit ne dispose pas de prix supplémentaires. Pour ajouter un prix " +"veuillez cliquer ajouter ou ajoutez les éléments depuis un autre produit." + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: content/variation.py:52 +msgid "description_price" +msgstr "" +"Si plusieurs variations de différentes catégories disposent d'un prix " +"unique, le prix combiné des produits correspondra au prix le plus élevé." + +#. Default: "Shipment methods for this product" +#: content/product.py:68 +msgid "description_shipment_methods" +msgstr "Types de livraison disponibles pour ce produit" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: order.py:475 +msgid "email_customer_body" +msgstr "" +"Très cher/chère ${name}\n" +"\n" +"Votre commande a été enregistrée avec succès. Veuillez trouver l'aperçu\n" +"complet de votre commande ci-après.\n" +"\n" +"Numéro de commande: ${orderid}\n" +"\n" +"${cart}\n" +"Monnaie: ${currency}\n" +"\n" +"\n" +"Adresse:\n" +"${address}\n" +"\n" +"Paiement:\n" +"${payment}\n" +"\n" +"Livraison:\n" +"${shipments}\n" +"\n" +"\n" +"Si vous avez des questions concernant votre achat, n'hésitez pas à nous\n" +"contacter par ${from_email}.\n" +"\n" +"Meilleurs remerciements\n" +"\n" +"${from_name}" + +#. Default: "Confirmation e-mail" +#: order.py:402 +msgid "email_customer_title" +msgstr "Confirmation de commande" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: order.py:454 +msgid "email_order_body" +msgstr "" +"Nouvelle commande par ${name}\n" +"\n" +"Numéro de commande: ${orderid}\n" +"\n" +"${cart}\n" +"Monnaie: ${currency}\n" +"\n" +"\n" +"Adresse:\n" +"${address}\n" +"\n" +"Paiement:\n" +"${payment}\n" +"\n" +"Livraison:\n" +"${shipments}" + +#. Default: "New order [${orderid}]" +#: order.py:393 +msgid "email_order_title" +msgstr "Nouvelle commande [${orderid}]" + +#. Default: "general terms and conditions" +#: browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "Conditions générales d'affaires" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: browser/images.pt:35 +msgid "info_Image" +msgstr "Ceci est l'affichage des images d'une variation du produit ${product}." + +#. Default: "You are currently looking at a variation of the product ${product}." +#: browser/variation.pt:25 +msgid "info_variation" +msgstr "Ceci est la variation du produit ${product}." + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "Ceci est l'affichage des prix d'une variation du produit ${product}." + +#. Default: "Address" +#: browser/orders.py:73 +msgid "label_address" +msgstr "Adresse" + +#. Default: "Cancelled" +#: browser/orders.py:37 +msgid "label_cancelled" +msgstr "Annulé" + +#. Default: "Currency" +#: browser/orders.py:59 +msgid "label_currency" +msgstr "Monnaie" + +#. Default: "Date" +#: browser/orders.py:56 +msgid "label_date" +msgstr "Date" + +#. Default: "Failed" +#: browser/orders.py:36 +msgid "label_failed" +msgstr "Echoué" + +#. Default: "Initialized" +#: browser/orders.py:33 +msgid "label_initialized" +msgstr "Passée" + +#. Default: "Order id" +#: browser/orders.py:50 +msgid "label_order_id" +msgstr "Numéro de commande" + +#. Default: "Order status" +#: browser/orders.py:66 +msgid "label_order_state" +msgstr "Etat de la commande" + +#. Default: "Price total" +#: browser/orders.py:62 +msgid "label_price_total" +msgstr "Prix total" + +#. Default: "Processed" +#: browser/orders.py:35 +msgid "label_processed" +msgstr "Traitée" + +#. Default: "Products" +#: browser/orders.py:77 +msgid "label_products" +msgstr "Produits" + +#. Default: "Sent" +#: browser/orders.py:34 +msgid "label_sent" +msgstr "Envoyée" + +#. Default: "Shipment methods" +#: content/product.py:67 +msgid "label_shipment_methods" +msgstr "Types de livraison" + +#. Default: "Shipment id's" +#: browser/orders.py:81 +msgid "label_shipmentids" +msgstr "Identifiants des types de livraison" + +#. Default: "User id" +#: browser/orders.py:53 +msgid "label_user_id" +msgstr "Nom d'utilisateur" + +#. Default: "Zone" +#: browser/orders.py:69 +msgid "label_zone" +msgstr "Zone" + +#. Default: "log in" +#: browser/cart.pt:101 +msgid "log_in" +msgstr "Veuillez vous connecter" + +#. Default: "Check out canceled" +#: browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "Commande annulée" + +#. Default: "Check out failed" +#: browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "Commande échouée" + +#. Default: "${offer} instead of ${price}" +#: browser/macros.pt:11 +msgid "price_offer" +msgstr "${offer} au lieu de ${price}" + +#. Default: "registration form" +#: browser/cart.pt:108 +msgid "registration_form" +msgstr "formulaire d'enregistrement" + +#. Default: "remove" +#: browser/configlet.pt:168 +msgid "remove" +msgstr "supprimer" + +#. Default: "Please supply an order id." +#: browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "Veuillez indiquer un numéro de commande." + +#. Default: "Please check the order id." +#: browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "Veuillez contrôler le numéro de commande." + +#. Default: "Manage orders" +#: browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "Gérer les commandes" + +#. Default: "Which one?" +#: browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "Laquelle?" + +#. Default: "Order details" +#: browser/order_details.pt:17 +msgid "title_order_details" +msgstr "Informations à propos de la commande" + +#. Default: "The order could not be found." +#: browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "La commande n'a pas été trouvée." diff --git a/src/pcommerce/core/locales/fr/LC_MESSAGES/plone.po b/src/pcommerce/core/locales/fr/LC_MESSAGES/plone.po new file mode 100755 index 0000000..aae0596 --- /dev/null +++ b/src/pcommerce/core/locales/fr/LC_MESSAGES/plone.po @@ -0,0 +1,55 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2008-04-07 14:15-100\n" +"PO-Revision-Date: 2007-11-01 10:18+0100\n" +"Last-Translator: Steve Beyeler \n" +"Language-Team: Français \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language-code: fr\n" +"Language-name: Français\n" +"Preferred-encodings: utf-8 latin1\n" +"Domain: plone\n" +"X-is-fallback-for: fr-ch fr-fr fr-be\n" +"X-Poedit-Language: Français\n" +"X-Poedit-Country: FRANCE\n" +"X-Poedit-SourceCharset: utf-8\n" + +msgid "Price" +msgstr "Prix" + +msgid "A price" +msgstr "Un prix" + +msgid "Product" +msgstr "Produit" + +msgid "A product" +msgstr "Un produit" + +msgid "Variation" +msgstr "Variation" + +msgid "A variation of a product" +msgstr "Un variation d'un produit" + +msgid "Variations" +msgstr "Variations" + +msgid "Prices" +msgstr "Prix" + +msgid "PCommerce configuration" +msgstr "Paramètres PCommerce" + +msgid "Shop" +msgstr "Shop" + +msgid "ShopFolder" +msgstr "Dossier shop" + +msgid "Images" +msgstr "Images" diff --git a/src/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po b/src/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po new file mode 100644 index 0000000..91e8426 --- /dev/null +++ b/src/pcommerce/core/locales/nl/LC_MESSAGES/pcommerce.po @@ -0,0 +1,754 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" +"Last-Translator: Albert Peschar \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: nl\n" +"Language-Name: Nederlands\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: pcommerce\n" + +#. Default: "Add image" +#: browser/images.pt:23 +msgid "Add image" +msgstr "Voeg afbeelding toe" + +#. Default: "Add price" +#: browser/prices.pt:24 +msgid "Add price" +msgstr "Voeg prijs toe" + +#. Default: "Add variation" +#: browser/variations.pt:22 +msgid "Add variation" +msgstr "Voeg variant toe" + +#: browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "${count} items toegevoegd aan winkelmandje" + +#: browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "Item toegevoegd aan winkelmandje" + +#: content/variation.py:35 +msgid "Additional price" +msgstr "Extra prijs" + +#. Default: "Additional prices" +#: browser/prices.pt:27 +msgid "Additional prices" +msgstr "Extra prijzen" + +#: steps.py:10 +msgid "Address" +msgstr "Adres" + +#. Default: "Address 1" +#: browser/address.pt:139 +msgid "Address 1" +msgstr "Adres 1" + +#. Default: "Address 2" +#: browser/address.pt:166 +msgid "Address 2" +msgstr "Adres 2" + +#. Default: "Amount" +#: browser/cart.pt:42 +msgid "Amount" +msgstr "Aantal" + +#. Default: "Billing address" +#: browser/components/address.pt:12 +msgid "Billing address" +msgstr "Factuuradres" + +#: browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "Bestelling annuleren" + +#. Default: "Check out" +#: browser/cart.pt:34 +msgid "Check out" +msgstr "Bestellen" + +#. Default: "Company" +#: browser/address.pt:120 +msgid "Company" +msgstr "Bedrijf" + +#. Default: "Confirmation" +#: browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "Bevestiging" + +#: browser/checkout.py:255 +msgid "Continue shopping" +msgstr "Verder winkelen" + +#. Default: "Country" +#: browser/address.pt:224 +msgid "Country" +msgstr "Land" + +#. Default: "Edit cart" +#: browser/cart.pt:120 +msgid "Edit cart" +msgstr "Winkelmandje bewerken" + +#. Default: "Email" +#: browser/address.pt:294 +msgid "Email" +msgstr "E-mail" + +#. Default: "Email address" +#: browser/configlet.pt:116 +#, fuzzy +msgid "Email address" +msgstr "Factuuradres" + +#. Default: "First name" +#: browser/address.pt:64 +msgid "First name" +msgstr "Voornaam" + +#. Default: "GTC" +#: browser/configlet.pt:68 +msgid "GTC" +msgstr "Voorwaarden-pagina" + +#: content/product.py:59 +msgid "Hot product" +msgstr "Populair artikel" + +#. Default: "I accept the ${link}" +#: browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "Ik ga akkoord met de ${link}" + +#. Default: "Image" +#: browser/images.pt:63 +msgid "Image" +msgstr "Afbeelding" + +#. Default: "Images" +#: browser/images.pt:26 +msgid "Images" +msgstr "Afbeeldingen" + +#. Default: "Last name" +#: browser/address.pt:92 +msgid "Last name" +msgstr "Achternaam" + +#. Default: "Manage orders" +#: profiles/default/actions.xml +msgid "Manage orders" +msgstr "Bestellingen beheren" + +#. Default: "Mr." +#: browser/address.pt:46 +msgid "Mr." +msgstr "Dhr." + +#. Default: "Mrs. / Ms." +#: browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "Mw. / Mej." + +#: content/product.py:51 +msgid "New product" +msgstr "Nieuw artikel" + +#. Default: "New products in our shop" +#: browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "Nieuwe artikelen in onze winkel" + +#: browser/checkout.py:258 +msgid "Next step" +msgstr "Volgende stap" + +#: browser/orders.py:110 +msgid "No" +msgstr "Aantal" + +#. Default: "No of articles:" +#: browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "Aantal artikelen:" + +#. Default: "Overview" +#: browser/components/overview.pt:9 +msgid "Overview" +msgstr "Overzicht" + +#. Default: "PCommerce configuration" +#: browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "PCommerce-instellingen" + +#. Default: "Payment" +#: browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "Betaling" + +#: browser/checkout.py:331 +msgid "Payment canceled" +msgstr "Betaling geannuleerd" + +#: browser/checkout.py:316 +msgid "Payment failed" +msgstr "Betaling mislukt" + +#. Default: "Phone" +#: browser/address.pt:322 +msgid "Phone" +msgstr "Telefoon" + +#: browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "Vul alstublieft een decimaal getal in (bijv. 7.6)" + +#: browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "Geef alstublieft een naam van de belasting op" + +#: browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "Geef alstublieft een zone-naam op" + +#: browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "Kies een betaalmethode." + +#: browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "Kies een verzendmethode." + +#: browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "Kies een variant." + +#: browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "Geef een aantal op." + +#. Default: "Post checkout" +#: browser/configlet.pt:92 +msgid "Post checkout" +msgstr "Pagina na bestellen" + +#: browser/checkout.py:247 +msgid "Previous step" +msgstr "Vorige stap" + +#. Default: "Price" +#: browser/cart.pt:43 +msgid "Price" +msgstr "Prijs" + +#. Default: "Price total" +#: browser/cart.pt:44 +msgid "Price total" +msgstr "Totale prijs" + +#: browser/checkout.py:246 +msgid "Print" +msgstr "Afdrukken" + +#. Default: "Product" +#: browser/cart.pt:41 +msgid "Product" +msgstr "Artikel" + +#. Default: "Product highlights" +#: browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "Uitgelichte artikelen" + +#. Default: "Product variations" +#: browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "Varianten van dit artikel" + +#. Default: "Productname" +#: browser/configlet.pt:36 +msgid "Productname" +msgstr "Artikelnaam" + +#. Default: "Related products" +#: browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "Verwante artikelen" + +#. Default: "Remove" +#: browser/cart.pt:45 +msgid "Remove" +msgstr "Verwijderen" + +#: browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "${count} items verwijderd uit winkelmandje" + +#: browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "Item verwijderd uit winkelmandje" + +#. Default: "Salutation" +#: browser/address.pt:35 +msgid "Salutation" +msgstr "Aanhef" + +#. Default: "Select the desired payment method" +#: browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "Kies de gewenste betaalmethode" + +#. Default: "Select the desired shipment method" +#: browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "Kies de gewenste verzendmethode" + +#. Default: "Select the desired shipment method for the following products:" +#: browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "Kies de gewenste verzendmethode voor de volgende artikelen:" + +#: browser/checkout.py:257 +msgid "Send order" +msgstr "Bestelling versturen" + +#. Default: "Shipment" +#: browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "Verzending" + +#: browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "Winkelmandje" + +#. Default: "Tax factor" +#: browser/configlet.pt:145 +msgid "Tax factor" +msgstr "Belastingpercentage" + +#. Default: "Tax included in product price" +#: browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "Belasting bij prijs inbegrepen" + +#. Default: "Tax name" +#: browser/configlet.pt:144 +msgid "Tax name" +msgstr "Belastingnaam" + +#. Default: "Taxes" +#: browser/configlet.pt:138 +msgid "Taxes" +msgstr "Belastingen" + +#. Default: "Thank you!" +#: browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "Dank u!" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "" + +#: browser/components/gtc.py:17 +msgid "" +"The general terms and conditions have to be accepted to finish your check " +"out." +msgstr "" +"U kunt de bestelling pas afronden als u de algemene voorwaarden aanvaardt." + +#. Default: "The name appearing in payment-terminals" +#: browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "De naam die verschijnt op afschriften" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: browser/configlet.pt:73 +msgid "" +"The path to the page holding the general terms and conditions to accept " +"before payment" +msgstr "" +"Het pad naar de pagina waarop de voorwaarden staan die men dient te " +"aanvaarden voor betaling" + +#. Default: "The path to the page to be redirected to after checkout" +#: browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "Het pad naar de pagina waarheen na betaling doorgestuurd wordt." + +#. Default: "Total" +#: browser/cart.pt:78 +msgid "Total" +msgstr "Totaal" + +#. Default: "Total ${currency}:" +#: browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "Totaal ${currency}:" + +#. Default: "Total incl. ${taxname}" +#: browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "Totaal incl. ${taxname}" + +#: order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "Totaal incl. ${tax}% ${taxname}" + +#. Default: "Total incl. charges" +#: browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "Totaal incl. kosten" + +#. Default: "Total incl. charges and ${taxname}" +#: browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "Totaal incl. kosten en ${taxname}" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "Totaal incl. kosten and ${tax}% ${taxname}" + +#: content/variation.py:26 +msgid "Type" +msgstr "Type" + +#. Default: "Variations" +#: browser/variations.pt:25 +msgid "Variations" +msgstr "Varianten" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: browser/components/confirmation.pt:12 +msgid "" +"We successfully received your order. An Email has been sent to you " +"containing all the order details." +msgstr "" +"Uw bestelling is in goede orde ontvangen. Er is een e-mail naar u verstuurd " +"met de details van uw bestelling." + +#: browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "U hebt nog geen artikelen aan uw winkelmandje toegevoegd." + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: browser/cart.pt:108 +msgid "" +"You have to be registered to check out your order, either ${log_in} if you " +"already have an account or head over to the ${registration_form} if you " +"don't." +msgstr "" +"U kunt alleen bestellen als u bent ingelogd. ${log_in} als u al een account " +"heeft, of ga anders naar het ${registration_form}" + +#. Default: "Your shopping cart" +#: browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "Uw winkelmandje" + +#. Default: "Your shopping cart is empty" +#: browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "Uw winkelmandje is leeg" + +#. Default: "ZIP / City" +#: browser/address.pt:185 +msgid "ZIP / City" +msgstr "Postcode / Stad" + +#. Default: "Zone" +#: browser/address.pt:253 +msgid "Zone" +msgstr "Zone" + +#. Default: "add" +#: browser/configlet.pt:192 +msgid "add" +msgstr "toevoegen" + +#. Default: "add to cart" +#: browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "toevoegen aan winkelmandje" + +#. Default: "Check out" +#: browser/checkout.pt:15 +msgid "checkout_title" +msgstr "Bestellen" + +#. Default: "List of all orders and their statuses" +#: profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "Lijst van bestellingen en hun status" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: browser/images.pt:40 +msgid "description_no_images" +msgstr "" +"Dit artikel heeft geen afbeeldingen. Om een afbeelding toe te voegen, klik " +"op de knop Toevoegen, of knip-en-plak een afbeelding van een andere plek." + +#. Default: "No orders were found." +#: browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "Geen bestellingen gevonden" + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" +"Dit artikel heeft geen prijzen. Om een prijs toe te voegen, klik op de knop " +"Toevoegen, of knip-en-plak een prijs van een andere plek." + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: content/variation.py:52 +msgid "description_price" +msgstr "" +"Als meerdere geselecteerde varianten in verschillende categoriën " +"verschillende prijzen hebben wordt de hoogste prijs gebruikt voor de prijs " +"van de geselecteerde combinatie." + +#. Default: "Shipment methods for this product" +#: content/product.py:68 +msgid "description_shipment_methods" +msgstr "Verzendingsmethoden voor dit artikel" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: order.py:475 +msgid "email_customer_body" +msgstr "" +"Geachte ${name},\n" +"\n" +"Uw bestelling is geplaatst. Hieronder vindt u een overzicht van uw " +"bestelling.\n" +"\n" +"Bestellingsnummer: ${orderid}\n" +"\n" +"${cart}\n" +"Valuta: ${currency}\n" +"\n" +"\n" +"Adres:\n" +"${address}\n" +"\n" +"Betaling:\n" +"${payment}\n" +"\n" +"Verzending:\n" +"${shipments}\n" +"\n" +"\n" +" Als u vragen hebt over uw bestelling, schroom dan niet om contact met ons " +"op te nemen op het adres ${from_email}.\n" +"\n" +" Met vriendelijke groet,\n" +"\n" +"${from_name}" + +#. Default: "Confirmation e-mail" +#: order.py:402 +msgid "email_customer_title" +msgstr "Bevestigingsmail" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: order.py:454 +msgid "email_order_body" +msgstr "" +"Nieuwe bestelling van ${name}\n" +"\n" +"Bestellingsnummer: ${orderid}\n" +"\n" +"${cart}\n" +"Valuta: ${currency}\n" +"\n" +"\n" +"Adres:\n" +"${address}\n" +"\n" +"Betaling:\n" +"${payment}\n" +"\n" +"Verzending:\n" +"${shipments}" + +#. Default: "New order [${orderid}]" +#: order.py:393 +msgid "email_order_title" +msgstr "Nieuwe bestelling [${orderid}]" + +#. Default: "general terms and conditions" +#: browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "Algemene voorwaarden" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: browser/images.pt:35 +msgid "info_Image" +msgstr "Dit zijn de afbeeldingen van een variant van artikel ${product}" + +#. Default: "You are currently looking at a variation of the product ${product}." +#: browser/variation.pt:25 +msgid "info_variation" +msgstr "Dit is een variant van artikel ${product}" + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "Dit zijn de prijzen van een variant van artikel ${product}" + +#. Default: "Address" +#: browser/orders.py:73 +msgid "label_address" +msgstr "Adres" + +#. Default: "Cancelled" +#: browser/orders.py:37 +msgid "label_cancelled" +msgstr "Geannuleerd" + +#. Default: "Currency" +#: browser/orders.py:59 +msgid "label_currency" +msgstr "Valuta" + +#. Default: "Date" +#: browser/orders.py:56 +msgid "label_date" +msgstr "Datum" + +#. Default: "Failed" +#: browser/orders.py:36 +msgid "label_failed" +msgstr "Mislukt" + +#. Default: "Initialized" +#: browser/orders.py:33 +msgid "label_initialized" +msgstr "Geinitialiseerd" + +#. Default: "Order id" +#: browser/orders.py:50 +msgid "label_order_id" +msgstr "Order nummer" + +#. Default: "Order status" +#: browser/orders.py:66 +msgid "label_order_state" +msgstr "Order status" + +#. Default: "Price total" +#: browser/orders.py:62 +msgid "label_price_total" +msgstr "Totale prijs" + +#. Default: "Processed" +#: browser/orders.py:35 +msgid "label_processed" +msgstr "Verwerkt" + +#. Default: "Products" +#: browser/orders.py:77 +msgid "label_products" +msgstr "Artikelen" + +#. Default: "Sent" +#: browser/orders.py:34 +msgid "label_sent" +msgstr "Verzonden" + +#. Default: "Shipment methods" +#: content/product.py:67 +msgid "label_shipment_methods" +msgstr "Verzendmethodes" + +#. Default: "Shipment id's" +#: browser/orders.py:81 +msgid "label_shipmentids" +msgstr "Zending nummer" + +#. Default: "User id" +#: browser/orders.py:53 +msgid "label_user_id" +msgstr "Gebruikers id" + +#. Default: "Zone" +#: browser/orders.py:69 +msgid "label_zone" +msgstr "Gebied" + +#. Default: "log in" +#: browser/cart.pt:101 +msgid "log_in" +msgstr "Log in" + +#. Default: "Check out canceled" +#: browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "Bestelling geannuleerd" + +#. Default: "Check out failed" +#: browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "Bestelling mislukt" + +#. Default: "${offer} instead of ${price}" +#: browser/macros.pt:11 +msgid "price_offer" +msgstr "${offer} in plaats van ${price}" + +#. Default: "registration form" +#: browser/cart.pt:108 +msgid "registration_form" +msgstr "aanmeldformulier" + +#. Default: "remove" +#: browser/configlet.pt:168 +msgid "remove" +msgstr "verwijder" + +#. Default: "Please supply an order id." +#: browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "Geef een ordernummer" + +#. Default: "Please check the order id." +#: browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "" + +#. Default: "Manage orders" +#: browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "Bestellingen beheren" + +#. Default: "Which one?" +#: browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "Welke?" + +#. Default: "Order details" +#: browser/order_details.pt:17 +msgid "title_order_details" +msgstr "Order details" + +#. Default: "The order could not be found." +#: browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "Order werd niet gevonden." diff --git a/src/pcommerce/core/locales/nl/LC_MESSAGES/plone.po b/src/pcommerce/core/locales/nl/LC_MESSAGES/plone.po new file mode 100644 index 0000000..01d631d --- /dev/null +++ b/src/pcommerce/core/locales/nl/LC_MESSAGES/plone.po @@ -0,0 +1,52 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2011-08-31 15:40+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" +"Last-Translator: Albert Peschar \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: nl\n" +"Language-Name: Nederlands\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: plone\n" + +msgid "Price" +msgstr "Prijs" + +msgid "A price" +msgstr "Een prijs" + +msgid "Product" +msgstr "Artikel" + +msgid "A product" +msgstr "Een artikel" + +msgid "Variation" +msgstr "Variant" + +msgid "A variation of a product" +msgstr "Een variant van een artikel" + +msgid "Variations" +msgstr "Varianten" + +msgid "Prices" +msgstr "Prijzen" + +msgid "PCommerce configuration" +msgstr "PCommerce-instellingen" + +msgid "Shop" +msgstr "Winkel" + +msgid "ShopFolder" +msgstr "Winkel-Map" + +msgid "Images" +msgstr "Afbeeldingen" diff --git a/src/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po b/src/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po new file mode 100644 index 0000000..9af0626 --- /dev/null +++ b/src/pcommerce/core/locales/no/LC_MESSAGES/pcommerce.po @@ -0,0 +1,752 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: 2011-11-18 10:41+0100\n" +"Last-Translator: Espen Moe-Nilssen \n" +"Language-Team: Espen Moe-Nilssen \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: no\n" +"Language-Name: Norwegian bokmål\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: plone\n" +"X-Poedit-Language: Norwegian Bokmal\n" +"X-Poedit-Country: NORWAY\n" + +#. Default: "Add image" +#: browser/images.pt:23 +msgid "Add image" +msgstr "Legg til bilde" + +#. Default: "Add price" +#: browser/prices.pt:24 +msgid "Add price" +msgstr "Legg til pris" + +#. Default: "Add variation" +#: browser/variations.pt:22 +msgid "Add variation" +msgstr "Legg til variant" + +#: browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "${count} lagt til i handlekurven" + +#: browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "Produkt lagt til i handlekurv" + +#: content/variation.py:35 +msgid "Additional price" +msgstr "Ekstra pris" + +#. Default: "Additional prices" +#: browser/prices.pt:27 +msgid "Additional prices" +msgstr "Ekstra priser" + +#: steps.py:10 +msgid "Address" +msgstr "Adresse" + +#. Default: "Address 1" +#: browser/address.pt:139 +msgid "Address 1" +msgstr "Adresse 1" + +#. Default: "Address 2" +#: browser/address.pt:166 +msgid "Address 2" +msgstr "Adresse 2" + +#. Default: "Amount" +#: browser/cart.pt:42 +msgid "Amount" +msgstr "Sum" + +#. Default: "Billing address" +#: browser/components/address.pt:12 +msgid "Billing address" +msgstr "Fakturaadresse" + +#: browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "Avbryt bestilling" + +#. Default: "Check out" +#: browser/cart.pt:34 +msgid "Check out" +msgstr "Bestille" + +#. Default: "Company" +#: browser/address.pt:120 +msgid "Company" +msgstr "Firma" + +#. Default: "Confirmation" +#: browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "Bekreftelse" + +#: browser/checkout.py:255 +msgid "Continue shopping" +msgstr "Fortsette å handle" + +#. Default: "Country" +#: browser/address.pt:224 +msgid "Country" +msgstr "Land" + +#. Default: "Edit cart" +#: browser/cart.pt:120 +msgid "Edit cart" +msgstr "Rediger handlekurv" + +#. Default: "Email" +#: browser/address.pt:294 +msgid "Email" +msgstr "E.post" + +#. Default: "Email address" +#: browser/configlet.pt:116 +#, fuzzy +msgid "Email address" +msgstr "Fakturaadresse" + +#. Default: "First name" +#: browser/address.pt:64 +msgid "First name" +msgstr "Fornavn" + +#. Default: "GTC" +#: browser/configlet.pt:68 +msgid "GTC" +msgstr "Generelle vilkår" + +#: content/product.py:59 +msgid "Hot product" +msgstr "Populært produkt" + +#. Default: "I accept the ${link}" +#: browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "Jeg godtar ${link}" + +#. Default: "Image" +#: browser/images.pt:63 +msgid "Image" +msgstr "Bilde" + +#. Default: "Images" +#: browser/images.pt:26 +msgid "Images" +msgstr "Bilder" + +#. Default: "Last name" +#: browser/address.pt:92 +msgid "Last name" +msgstr "Etternavn" + +#. Default: "Manage orders" +#: profiles/default/actions.xml +msgid "Manage orders" +msgstr "Administrere bestillinger" + +#. Default: "Mr." +#: browser/address.pt:46 +msgid "Mr." +msgstr "Hr." + +#. Default: "Mrs. / Ms." +#: browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "Ms." + +#: content/product.py:51 +msgid "New product" +msgstr "Nytt produkt" + +#. Default: "New products in our shop" +#: browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "Nytt produkt hos oss" + +#: browser/checkout.py:258 +msgid "Next step" +msgstr "Neste steg" + +#: browser/orders.py:110 +msgid "No" +msgstr "Produktnummer" + +#. Default: "No of articles:" +#: browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "Antall produkter:" + +#. Default: "Overview" +#: browser/components/overview.pt:9 +msgid "Overview" +msgstr "Oversikt" + +#. Default: "PCommerce configuration" +#: browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "PCommerce-instillinger" + +#. Default: "Payment" +#: browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "Betaling" + +#: browser/checkout.py:331 +msgid "Payment canceled" +msgstr "Betaling avbrutt" + +#: browser/checkout.py:316 +msgid "Payment failed" +msgstr "Betaling mislykkes" + +#. Default: "Phone" +#: browser/address.pt:322 +msgid "Phone" +msgstr "Telefon" + +#: browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "Vennligst skriv inn et desimalnummer (f.eks 7,6)" + +#: browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "Vennligst oppgi skattenavn" + +#: browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "Vennligst skriv inn sone navn" + +#: browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "Velg betalingsmåte" + +#: browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "Velg forsendelsesmåte" + +#: browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "Velg en variant" + +#: browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "Skriv inn mengde" + +#. Default: "Post checkout" +#: browser/configlet.pt:92 +msgid "Post checkout" +msgstr "Side etter bestilling" + +#: browser/checkout.py:247 +msgid "Previous step" +msgstr "Forige steg" + +#. Default: "Price" +#: browser/cart.pt:43 +msgid "Price" +msgstr "Pris" + +#. Default: "Price total" +#: browser/cart.pt:44 +msgid "Price total" +msgstr "Totalpris" + +#: browser/checkout.py:246 +msgid "Print" +msgstr "Skriv ut" + +#. Default: "Product" +#: browser/cart.pt:41 +msgid "Product" +msgstr "Produkt" + +#. Default: "Product highlights" +#: browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "Aktuelle artikler" + +#. Default: "Product variations" +#: browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "Produktvariant" + +#. Default: "Productname" +#: browser/configlet.pt:36 +msgid "Productname" +msgstr "Produktnavn" + +#. Default: "Related products" +#: browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "Relative produkter" + +#. Default: "Remove" +#: browser/cart.pt:45 +msgid "Remove" +msgstr "Slett" + +#: browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "${count} produkter fjernet fra handlekurven" + +#: browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "Fjernet produktet fra handlekurv" + +#. Default: "Salutation" +#: browser/address.pt:35 +msgid "Salutation" +msgstr "Tittel" + +#. Default: "Select the desired payment method" +#: browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "Velg betalingsmetode" + +#. Default: "Select the desired shipment method" +#: browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "Velg forsendelsesmåte" + +#. Default: "Select the desired shipment method for the following products:" +#: browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "Velg forsendelsesmåte for følgende produkter:" + +#: browser/checkout.py:257 +msgid "Send order" +msgstr "bestillingen er sendt" + +#. Default: "Shipment" +#: browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "Forsending" + +#: browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "Handlekurv" + +#. Default: "Tax factor" +#: browser/configlet.pt:145 +msgid "Tax factor" +msgstr "Skatteprosent" + +#. Default: "Tax included in product price" +#: browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "Skatt er inkludert i produktprisen" + +#. Default: "Tax name" +#: browser/configlet.pt:144 +msgid "Tax name" +msgstr "Skattenavn" + +#. Default: "Taxes" +#: browser/configlet.pt:138 +msgid "Taxes" +msgstr "Skatter" + +#. Default: "Thank you!" +#: browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "Takk!" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "" + +#: browser/components/gtc.py:17 +msgid "" +"The general terms and conditions have to be accepted to finish your check " +"out." +msgstr "Generelle vilkår må godtas før bestilling kan sendes" + +#. Default: "The name appearing in payment-terminals" +#: browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "Navnet som vises i betalings-terminaler" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: browser/configlet.pt:73 +msgid "" +"The path to the page holding the general terms and conditions to accept " +"before payment" +msgstr "Nettverksbanen til siden med de generelle vilkårene etc." + +#. Default: "The path to the page to be redirected to after checkout" +#: browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "Nettverksstien til siden en blir omdirigert til etter kassen" + +#. Default: "Total" +#: browser/cart.pt:78 +msgid "Total" +msgstr "Total" + +#. Default: "Total ${currency}:" +#: browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "Totalt ${currency}:" + +#. Default: "Total incl. ${taxname}" +#: browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "Totalt inkl. ${taxname}" + +#: order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "Totalt inkl. ${tax}% ${taxname}" + +#. Default: "Total incl. charges" +#: browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "Totalt inkl. kostnader" + +#. Default: "Total incl. charges and ${taxname}" +#: browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "Totalt inkl. kostnader og ${taxname}" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "Totalt inkl. kostnader og ${tax}% ${taxname}" + +#: content/variation.py:26 +msgid "Type" +msgstr "Type" + +#. Default: "Variations" +#: browser/variations.pt:25 +msgid "Variations" +msgstr "Varianter" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: browser/components/confirmation.pt:12 +msgid "" +"We successfully received your order. An Email has been sent to you " +"containing all the order details." +msgstr "" +"Vi har mottatt din bestilling. En e-post har blitt sendt til deg som " +"inneholder alle ordredetaljer." + +#: browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "Du har ennå ikke lagt til noen produkter i handlekurven din" + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: browser/cart.pt:108 +msgid "" +"You have to be registered to check out your order, either ${log_in} if you " +"already have an account or head over to the ${registration_form} if you " +"don't." +msgstr "" +"Du må være registrert for å sjekke ut din bestilling, enten ${log_in} hvis " +"du allerede har en konto eller gå over til ${registration_form} hvis ikke." + +#. Default: "Your shopping cart" +#: browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "Din handlekurv" + +#. Default: "Your shopping cart is empty" +#: browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "Handlevognen er tom" + +#. Default: "ZIP / City" +#: browser/address.pt:185 +msgid "ZIP / City" +msgstr "Postkode / Sted" + +#. Default: "Zone" +#: browser/address.pt:253 +msgid "Zone" +msgstr "Sone" + +#. Default: "add" +#: browser/configlet.pt:192 +msgid "add" +msgstr "legg til" + +#. Default: "add to cart" +#: browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "legg i handlekurv" + +#. Default: "Check out" +#: browser/checkout.pt:15 +msgid "checkout_title" +msgstr "Bestille" + +#. Default: "List of all orders and their statuses" +#: profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "Liste over alle ordrer og deres status" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: browser/images.pt:40 +msgid "description_no_images" +msgstr "" +"Dette produktet har ingen bilder. For å legge til et bilde, trykker du på " +"knappen Legg til, eller limer inn innhold fra et annet sted." + +#. Default: "No orders were found." +#: browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "Ingen bestillinger ble funnet." + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" +"Dette produktet har ingen ytterligere priser. For å legge til en pris, trykk " +"på knappen Legg til, eller lim inn innhold fra et annet sted." + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: content/variation.py:52 +msgid "description_price" +msgstr "" +"Hvis flere valgte variasjoner i ulike kategorier har enhetspriser, vil " +"større prisen bli regnskapsført i prisingen av den valgte kombinasjonen" + +#. Default: "Shipment methods for this product" +#: content/product.py:68 +msgid "description_shipment_methods" +msgstr "Forsendelsemetoder for dette produktet" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: order.py:475 +msgid "email_customer_body" +msgstr "" +"Kjære ${name} \n" +"\n" +"Bestillingen har med hell blitt registrert. Vennligst finne en komplett \n" +"oversikt over bestillingen din nedenfor. \n" +"\n" +"Order ID: ${orderid} \n" +"\n" +"${cart} \n" +"Valuta: ${currency} \n" +"\n" +"\n" +"Adresse: \n" +"${address} \n" +"\n" +"Betaling: \n" +"${payment} \n" +"\n" +"Forsendelse: \n" +"${shipments} \n" +"\n" +"\n" +"Hvis du har spørsmål angående kjøpet ikke nøl \n" +"å kontakte oss på ${from_email}. \n" +"\n" +"Beste hilsen \n" +"\n" +"${from_name}" + +#. Default: "Confirmation e-mail" +#: order.py:402 +msgid "email_customer_title" +msgstr "Bekreftelses-epost" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: order.py:454 +msgid "email_order_body" +msgstr "" +"Ny ordre av ${name} \n" +"\n" +"OrdreID: ${orderid} \n" +"\n" +"${cart} \n" +"Valuta: ${currency} \n" +"\n" +"\n" +"Adresse: \n" +"${address} \n" +"\n" +"Betaling: \n" +"${payment} \n" +"\n" +"Forsendelse: \n" +"${shipments}" + +#. Default: "New order [${orderid}]" +#: order.py:393 +msgid "email_order_title" +msgstr "Ny bestilling [${orderid}]" + +#. Default: "general terms and conditions" +#: browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "Generelle vilkår" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: browser/images.pt:35 +msgid "info_Image" +msgstr "Du er nå ser på bilder for en variant av produktet ${product}." + +#. Default: "You are currently looking at a variation of the product ${product}." +#: browser/variation.pt:25 +msgid "info_variation" +msgstr "Du ser for øyeblikket på en variant av produktet ${product}." + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "Du er nå ser på prisene for en variant av produktet ${product}." + +#. Default: "Address" +#: browser/orders.py:73 +msgid "label_address" +msgstr "Adresse" + +#. Default: "Cancelled" +#: browser/orders.py:37 +msgid "label_cancelled" +msgstr "Avbrutt" + +#. Default: "Currency" +#: browser/orders.py:59 +msgid "label_currency" +msgstr "Valuta" + +#. Default: "Date" +#: browser/orders.py:56 +msgid "label_date" +msgstr "Dato" + +#. Default: "Failed" +#: browser/orders.py:36 +msgid "label_failed" +msgstr "Mislykket" + +#. Default: "Initialized" +#: browser/orders.py:33 +msgid "label_initialized" +msgstr "Initialisert" + +#. Default: "Order id" +#: browser/orders.py:50 +msgid "label_order_id" +msgstr "Ordrenummer" + +#. Default: "Order status" +#: browser/orders.py:66 +msgid "label_order_state" +msgstr "Ordrestatus" + +#. Default: "Price total" +#: browser/orders.py:62 +msgid "label_price_total" +msgstr "Totalpris" + +#. Default: "Processed" +#: browser/orders.py:35 +msgid "label_processed" +msgstr "Fortsett" + +#. Default: "Products" +#: browser/orders.py:77 +msgid "label_products" +msgstr "Produkter" + +#. Default: "Sent" +#: browser/orders.py:34 +msgid "label_sent" +msgstr "Sendt" + +#. Default: "Shipment methods" +#: content/product.py:67 +msgid "label_shipment_methods" +msgstr "Forsendelsesmetode" + +#. Default: "Shipment id's" +#: browser/orders.py:81 +msgid "label_shipmentids" +msgstr "Sendingsnummer" + +#. Default: "User id" +#: browser/orders.py:53 +msgid "label_user_id" +msgstr "Brukerid" + +#. Default: "Zone" +#: browser/orders.py:69 +msgid "label_zone" +msgstr "Sone" + +#. Default: "log in" +#: browser/cart.pt:101 +msgid "log_in" +msgstr "Logg inn" + +#. Default: "Check out canceled" +#: browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "Bestilling avbrutt" + +#. Default: "Check out failed" +#: browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "Bestilling mislykkes" + +#. Default: "${offer} instead of ${price}" +#: browser/macros.pt:11 +msgid "price_offer" +msgstr "${offer} i stedet for ${price}" + +#. Default: "registration form" +#: browser/cart.pt:108 +msgid "registration_form" +msgstr "Søknadsskjema" + +#. Default: "remove" +#: browser/configlet.pt:168 +msgid "remove" +msgstr "slett" + +#. Default: "Please supply an order id." +#: browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "Angi et ordrenummer" + +#. Default: "Please check the order id." +#: browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "Vennligst sjekk ordreID" + +#. Default: "Manage orders" +#: browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "Behandle ordrer" + +#. Default: "Which one?" +#: browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "Hvilken?" + +#. Default: "Order details" +#: browser/order_details.pt:17 +msgid "title_order_details" +msgstr "Ordredetaljer" + +#. Default: "The order could not be found." +#: browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "Ordren ble ikke funnet" diff --git a/src/pcommerce/core/locales/no/LC_MESSAGES/plone.po b/src/pcommerce/core/locales/no/LC_MESSAGES/plone.po new file mode 100644 index 0000000..b3b9701 --- /dev/null +++ b/src/pcommerce/core/locales/no/LC_MESSAGES/plone.po @@ -0,0 +1,56 @@ +msgid "" +msgstr "" +"Project-Id-Version: pcommerce.core\n" +"POT-Creation-Date: 2011-08-31 15:40+0000\n" +"PO-Revision-Date: 2011-11-17 13:30+0100\n" +"Last-Translator: Espen Moe-Nilssen \n" +"Language-Team: Espen Moe-Nilssen \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: no\n" +"Language-Name: Norwegian bokmål\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: plone\n" +"X-Poedit-Language: Norwegian Bokmal\n" +"X-Poedit-Country: NORWAY\n" + +msgid "Price" +msgstr "Pris" + +msgid "A price" +msgstr "En pris" + +msgid "Product" +msgstr "Produkt" + +msgid "A product" +msgstr "Et produkt" + +msgid "Variation" +msgstr "Variant" + +msgid "A variation of a product" +msgstr "En variant av produktet" + +msgid "Variations" +msgstr "Varianter" + +msgid "Prices" +msgstr "Priser" + +msgid "PCommerce configuration" +msgstr "PCommerce-instillinger" + +msgid "Shop" +msgstr "Butikk" + +msgid "ShopFolder" +msgstr "Butikkfolder" + +msgid "Images" +msgstr "Bilder" + + diff --git a/src/pcommerce/core/locales/pcommerce.pot b/src/pcommerce/core/locales/pcommerce.pot new file mode 100644 index 0000000..cdd7ca3 --- /dev/null +++ b/src/pcommerce/core/locales/pcommerce.pot @@ -0,0 +1,690 @@ +# --- PLEASE EDIT THE LINES BELOW CORRECTLY --- +# SOME DESCRIPTIVE TITLE. +# FIRST AUTHOR , YEAR. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2012-02-06 08:30+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: en\n" +"Language-Name: English\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: pcommerce\n" + +#. Default: "Add image" +#: ./browser/images.pt:23 +msgid "Add image" +msgstr "" + +#. Default: "Add price" +#: ./browser/prices.pt:24 +msgid "Add price" +msgstr "" + +#. Default: "Add variation" +#: ./browser/variations.pt:22 +msgid "Add variation" +msgstr "" + +#: ./browser/viewlets/processor.py:46 +msgid "Added ${count} items to cart" +msgstr "" + +#: ./browser/viewlets/processor.py:48 +msgid "Added item to cart" +msgstr "" + +#: ./content/variation.py:35 +msgid "Additional price" +msgstr "" + +#. Default: "Additional prices" +#: ./browser/prices.pt:27 +msgid "Additional prices" +msgstr "" + +#: ./steps.py:10 +msgid "Address" +msgstr "" + +#. Default: "Address 1" +#: ./browser/address.pt:139 +msgid "Address 1" +msgstr "" + +#. Default: "Address 2" +#: ./browser/address.pt:166 +msgid "Address 2" +msgstr "" + +#. Default: "Amount" +#: ./browser/cart.pt:42 +msgid "Amount" +msgstr "" + +#. Default: "Billing address" +#: ./browser/components/address.pt:12 +msgid "Billing address" +msgstr "" + +#: ./browser/checkout.py:265 +msgid "Cancel checkout" +msgstr "" + +#. Default: "Check out" +#: ./browser/cart.pt:34 +msgid "Check out" +msgstr "" + +#. Default: "Company" +#: ./browser/address.pt:120 +msgid "Company" +msgstr "" + +#. Default: "Confirmation" +#: ./browser/components/confirmation.pt:17 +msgid "Confirmation" +msgstr "" + +#: ./browser/checkout.py:255 +msgid "Continue shopping" +msgstr "" + +#. Default: "Country" +#: ./browser/address.pt:224 +msgid "Country" +msgstr "" + +#. Default: "Edit cart" +#: ./browser/cart.pt:120 +msgid "Edit cart" +msgstr "" + +#. Default: "Email" +#: ./browser/address.pt:294 +msgid "Email" +msgstr "" + +#. Default: "Email address" +#: ./browser/configlet.pt:116 +msgid "Email address" +msgstr "" + +#. Default: "First name" +#: ./browser/address.pt:64 +msgid "First name" +msgstr "" + +#. Default: "GTC" +#: ./browser/configlet.pt:68 +msgid "GTC" +msgstr "" + +#: ./content/product.py:59 +msgid "Hot product" +msgstr "" + +#. Default: "I accept the ${link}" +#: ./browser/components/gtc.pt:17 +msgid "I accept the ${link}" +msgstr "" + +#. Default: "Image" +#: ./browser/images.pt:63 +msgid "Image" +msgstr "" + +#. Default: "Images" +#: ./browser/images.pt:26 +msgid "Images" +msgstr "" + +#. Default: "Last name" +#: ./browser/address.pt:92 +msgid "Last name" +msgstr "" + +#. Default: "Manage orders" +#: ./profiles/default/actions.xml +msgid "Manage orders" +msgstr "" + +#. Default: "Mr." +#: ./browser/address.pt:46 +msgid "Mr." +msgstr "" + +#. Default: "Mrs. / Ms." +#: ./browser/address.pt:52 +msgid "Mrs. / Ms." +msgstr "" + +#: ./content/product.py:51 +msgid "New product" +msgstr "" + +#. Default: "New products in our shop" +#: ./browser/viewlets/new.pt:2 +msgid "New products in our shop" +msgstr "" + +#: ./browser/checkout.py:258 +msgid "Next step" +msgstr "" + +#: ./browser/orders.py:110 +msgid "No" +msgstr "" + +#. Default: "No of articles:" +#: ./browser/portlets/cart.pt:18 +msgid "No of articles:" +msgstr "" + +#. Default: "Overview" +#: ./browser/components/overview.pt:9 +msgid "Overview" +msgstr "" + +#. Default: "PCommerce configuration" +#: ./browser/configlet.pt:13 +msgid "PCommerce configuration" +msgstr "" + +#. Default: "Payment" +#: ./browser/components/confirmation.pt:48 +msgid "Payment" +msgstr "" + +#: ./browser/checkout.py:331 +msgid "Payment canceled" +msgstr "" + +#: ./browser/checkout.py:316 +msgid "Payment failed" +msgstr "" + +#. Default: "Phone" +#: ./browser/address.pt:322 +msgid "Phone" +msgstr "" + +#: ./browser/configlet.py:43 +msgid "Please enter a floating point number (e.g. 7.6)" +msgstr "" + +#: ./browser/configlet.py:39 +msgid "Please provide a tax name" +msgstr "" + +#: ./browser/configlet.py:37 +msgid "Please provide a zone name" +msgstr "" + +#: ./browser/components/payments.py:17 +msgid "Please select a payment method." +msgstr "" + +#: ./browser/components/shipments.py:25 +msgid "Please select a shipment method." +msgstr "" + +#: ./browser/viewlets/processor.py:29 +msgid "Please select a variation" +msgstr "" + +#: ./browser/viewlets/processor.py:17 +msgid "Please specify an amount" +msgstr "" + +#. Default: "Post checkout" +#: ./browser/configlet.pt:92 +msgid "Post checkout" +msgstr "" + +#: ./browser/checkout.py:247 +msgid "Previous step" +msgstr "" + +#. Default: "Price" +#: ./browser/cart.pt:43 +msgid "Price" +msgstr "" + +#. Default: "Price total" +#: ./browser/cart.pt:44 +msgid "Price total" +msgstr "" + +#: ./browser/checkout.py:246 +msgid "Print" +msgstr "" + +#. Default: "Product" +#: ./browser/cart.pt:41 +msgid "Product" +msgstr "" + +#. Default: "Product highlights" +#: ./browser/viewlets/hot.pt:2 +msgid "Product highlights" +msgstr "" + +#. Default: "Product variations" +#: ./browser/viewlets/variation.pt:2 +msgid "Product variations" +msgstr "" + +#. Default: "Productname" +#: ./browser/configlet.pt:36 +msgid "Productname" +msgstr "" + +#. Default: "Related products" +#: ./browser/viewlets/related.pt:2 +msgid "Related products" +msgstr "" + +#. Default: "Remove" +#: ./browser/cart.pt:45 +msgid "Remove" +msgstr "" + +#: ./browser/viewlets/processor.py:50 +msgid "Removed ${count} items from cart" +msgstr "" + +#: ./browser/viewlets/processor.py:52 +msgid "Removed item from cart" +msgstr "" + +#. Default: "Salutation" +#: ./browser/address.pt:35 +msgid "Salutation" +msgstr "" + +#. Default: "Select the desired payment method" +#: ./browser/components/payments.pt:12 +msgid "Select the desired payment method" +msgstr "" + +#. Default: "Select the desired shipment method" +#: ./browser/components/shipments.pt:13 +msgid "Select the desired shipment method" +msgstr "" + +#. Default: "Select the desired shipment method for the following products:" +#: ./browser/components/shipments.pt:54 +msgid "Select the desired shipment method for the following products:" +msgstr "" + +#: ./browser/checkout.py:257 +msgid "Send order" +msgstr "" + +#. Default: "Shipment" +#: ./browser/components/confirmation.pt:30 +msgid "Shipment" +msgstr "" + +#: ./browser/portlets/cart.py:23 +msgid "Shopping cart" +msgstr "" + +#. Default: "Tax factor" +#: ./browser/configlet.pt:145 +msgid "Tax factor" +msgstr "" + +#. Default: "Tax included in product price" +#: ./browser/configlet.pt:206 +msgid "Tax included in product price" +msgstr "" + +#. Default: "Tax name" +#: ./browser/configlet.pt:144 +msgid "Tax name" +msgstr "" + +#. Default: "Taxes" +#: ./browser/configlet.pt:138 +msgid "Taxes" +msgstr "" + +#. Default: "Thank you!" +#: ./browser/components/confirmation.pt:9 +msgid "Thank you!" +msgstr "" + +#. Default: "The email address receiving and sending pcommerce related emails" +#: ./browser/configlet.pt:121 +msgid "The email address receiving and sending pcommerce related emails" +msgstr "" + +#: ./browser/components/gtc.py:17 +msgid "The general terms and conditions have to be accepted to finish your check out." +msgstr "" + +#. Default: "The name appearing in payment-terminals" +#: ./browser/configlet.pt:49 +msgid "The name appearing in payment-terminals" +msgstr "" + +#. Default: "The path to the page holding the general terms and conditions to accept before payment" +#: ./browser/configlet.pt:73 +msgid "The path to the page holding the general terms and conditions to accept before payment" +msgstr "" + +#. Default: "The path to the page to be redirected to after checkout" +#: ./browser/configlet.pt:97 +msgid "The path to the page to be redirected to after checkout" +msgstr "" + +#. Default: "Total" +#: ./browser/cart.pt:78 +msgid "Total" +msgstr "" + +#. Default: "Total ${currency}:" +#: ./browser/portlets/cart.pt:20 +msgid "Total ${currency}:" +msgstr "" + +#. Default: "Total incl. ${taxname}" +#: ./browser/macros.pt:158 +msgid "Total incl. ${taxname}" +msgstr "" + +#: ./order.py:341 +msgid "Total incl. ${tax}% ${taxname}" +msgstr "" + +#. Default: "Total incl. charges" +#: ./browser/macros.pt:131 +msgid "Total incl. charges" +msgstr "" + +#. Default: "Total incl. charges and ${taxname}" +#: ./browser/macros.pt:187 +msgid "Total incl. charges and ${taxname}" +msgstr "" + +#. Default: "Total incl. charges and ${tax}% ${taxname}" +#: ./browser/macros.pt:190 +msgid "Total incl. charges and ${tax}% ${taxname}" +msgstr "" + +#: ./content/variation.py:26 +msgid "Type" +msgstr "" + +#. Default: "Variations" +#: ./browser/variations.pt:25 +msgid "Variations" +msgstr "" + +#. Default: "We successfully received your order. An Email has been sent to you containing all the order details." +#: ./browser/components/confirmation.pt:12 +msgid "We successfully received your order. An Email has been sent to you containing all the order details." +msgstr "" + +#: ./browser/checkout.py:43 +msgid "You have not yet added any products to your cart" +msgstr "" + +#. Default: "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +#: ./browser/cart.pt:108 +msgid "You have to be registered to check out your order, either ${log_in} if you already have an account or head over to the ${registration_form} if you don't." +msgstr "" + +#. Default: "Your shopping cart" +#: ./browser/cart.pt:16 +msgid "Your shopping cart" +msgstr "" + +#. Default: "Your shopping cart is empty" +#: ./browser/cart.pt:20 +msgid "Your shopping cart is empty" +msgstr "" + +#. Default: "ZIP / City" +#: ./browser/address.pt:185 +msgid "ZIP / City" +msgstr "" + +#. Default: "Zone" +#: ./browser/address.pt:253 +msgid "Zone" +msgstr "" + +#. Default: "add" +#: ./browser/configlet.pt:192 +msgid "add" +msgstr "" + +#. Default: "add to cart" +#: ./browser/viewlets/buy.pt:19 +msgid "add to cart" +msgstr "" + +#. Default: "Check out" +#: ./browser/checkout.pt:15 +msgid "checkout_title" +msgstr "" + +#. Default: "List of all orders and their statuses" +#: ./profiles/default/actions.xml +msgid "description_manage_orders" +msgstr "" + +#. Default: "This product has no images. To add an image press the 'add' button or paste content from another location." +#: ./browser/images.pt:40 +msgid "description_no_images" +msgstr "" + +#. Default: "No orders were found." +#: ./browser/manage_orders.pt:17 +msgid "description_no_orders" +msgstr "" + +#. Default: "This product has no additional prices. To add a price press the 'add' button or paste content from another location." +#: ./browser/prices.pt:41 +msgid "description_no_prices" +msgstr "" + +#. Default: "If multiple selected variations in different categories have unit prices, the greater price will be accounted for in pricing of the selected combination." +#: ./content/variation.py:52 +msgid "description_price" +msgstr "" + +#. Default: "Shipment methods for this product" +#: ./content/product.py:68 +msgid "description_shipment_methods" +msgstr "" + +#. Default: "Dear ${name}\n\nYour order has been successfully registered. Please find a complete\noverview of your order below.\n\nOrder ID: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n\nIf you have any questions concerning your purchase do not hesitate\nto contact us at ${from_email}.\n\nBest regards\n\n${from_name}" +#: ./order.py:475 +msgid "email_customer_body" +msgstr "" + +#. Default: "Confirmation e-mail" +#: ./order.py:402 +msgid "email_customer_title" +msgstr "" + +#. Default: "New order by ${name}\n\nOrderid: ${orderid}\n\n${cart}\nCurrency: ${currency}\n\n\nAddress:\n${address}\n\nPayment:\n${payment}\n\nShipment:\n${shipments}\n\n" +#: ./order.py:454 +msgid "email_order_body" +msgstr "" + +#. Default: "New order [${orderid}]" +#: ./order.py:393 +msgid "email_order_title" +msgstr "" + +#. Default: "general terms and conditions" +#: ./browser/components/gtc.pt:17 +msgid "general terms and conditions" +msgstr "" + +#. Default: "You are currently looking at the images of a variation of the product ${product}." +#: ./browser/images.pt:35 +msgid "info_Image" +msgstr "" + +#. Default: "You are currently looking at a variation of the product ${product}." +#: ./browser/variation.pt:25 +msgid "info_variation" +msgstr "" + +#. Default: "You are currently looking at the prices of a variation of the product ${product}." +#: ./browser/prices.pt:36 +msgid "info_variation_prices" +msgstr "" + +#. Default: "Address" +#: ./browser/orders.py:73 +msgid "label_address" +msgstr "" + +#. Default: "Cancelled" +#: ./browser/orders.py:37 +msgid "label_cancelled" +msgstr "" + +#. Default: "Currency" +#: ./browser/orders.py:59 +msgid "label_currency" +msgstr "" + +#. Default: "Date" +#: ./browser/orders.py:56 +msgid "label_date" +msgstr "" + +#. Default: "Failed" +#: ./browser/orders.py:36 +msgid "label_failed" +msgstr "" + +#. Default: "Initialized" +#: ./browser/orders.py:33 +msgid "label_initialized" +msgstr "" + +#. Default: "Order id" +#: ./browser/orders.py:50 +msgid "label_order_id" +msgstr "" + +#. Default: "Order status" +#: ./browser/orders.py:66 +msgid "label_order_state" +msgstr "" + +#. Default: "Price total" +#: ./browser/orders.py:62 +msgid "label_price_total" +msgstr "" + +#. Default: "Processed" +#: ./browser/orders.py:35 +msgid "label_processed" +msgstr "" + +#. Default: "Products" +#: ./browser/orders.py:77 +msgid "label_products" +msgstr "" + +#. Default: "Sent" +#: ./browser/orders.py:34 +msgid "label_sent" +msgstr "" + +#. Default: "Shipment methods" +#: ./content/product.py:67 +msgid "label_shipment_methods" +msgstr "" + +#. Default: "Shipment id's" +#: ./browser/orders.py:81 +msgid "label_shipmentids" +msgstr "" + +#. Default: "User id" +#: ./browser/orders.py:53 +msgid "label_user_id" +msgstr "" + +#. Default: "Zone" +#: ./browser/orders.py:69 +msgid "label_zone" +msgstr "" + +#. Default: "log in" +#: ./browser/cart.pt:101 +msgid "log_in" +msgstr "" + +#. Default: "Check out canceled" +#: ./browser/checkout.py:359 +msgid "message_checkout_canceled" +msgstr "" + +#. Default: "Check out failed" +#: ./browser/checkout.py:373 +msgid "message_checkout_failed" +msgstr "" + +#. Default: "${offer} instead of ${price}" +#: ./browser/macros.pt:11 +msgid "price_offer" +msgstr "" + +#. Default: "registration form" +#: ./browser/cart.pt:108 +msgid "registration_form" +msgstr "" + +#. Default: "remove" +#: ./browser/configlet.pt:168 +msgid "remove" +msgstr "" + +#. Default: "Please supply an order id." +#: ./browser/order_details.pt:23 +msgid "text_no_order_id_supplied" +msgstr "" + +#. Default: "Please check the order id." +#: ./browser/order_details.pt:30 +msgid "text_order_not_found" +msgstr "" + +#. Default: "Manage orders" +#: ./browser/manage_orders.pt:13 +msgid "title_manage_orders" +msgstr "" + +#. Default: "Which one?" +#: ./browser/order_details.pt:21 +msgid "title_no_order_id_supplied" +msgstr "" + +#. Default: "Order details" +#: ./browser/order_details.pt:17 +msgid "title_order_details" +msgstr "" + +#. Default: "The order could not be found." +#: ./browser/order_details.pt:28 +msgid "title_order_not_found" +msgstr "" + diff --git a/src/pcommerce/core/locales/plone.pot b/src/pcommerce/core/locales/plone.pot new file mode 100644 index 0000000..58ccd22 --- /dev/null +++ b/src/pcommerce/core/locales/plone.pot @@ -0,0 +1,51 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2010-12-15 08:16+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" +"Language-Code: en\n" +"Language-Name: English\n" +"Preferred-Encodings: utf-8 latin1\n" +"Domain: plone\n" + +msgid "Price" +msgstr "" + +msgid "A price" +msgstr "" + +msgid "Product" +msgstr "" + +msgid "A product" +msgstr "" + +msgid "Variation" +msgstr "" + +msgid "A variation of a product" +msgstr "" + +msgid "Variations" +msgstr "" + +msgid "Prices" +msgstr "" + +msgid "PCommerce configuration" +msgstr "" + +msgid "Shop" +msgstr "" + +msgid "ShopFolder" +msgstr "" + +msgid "Images" +msgstr "" diff --git a/src/pcommerce/core/order.py b/src/pcommerce/core/order.py new file mode 100644 index 0000000..97c3797 --- /dev/null +++ b/src/pcommerce/core/order.py @@ -0,0 +1,569 @@ +import transaction +from time import time + +from BTrees.OOBTree import OOBTree +from persistent import Persistent +from persistent.list import PersistentList +from persistent.mapping import PersistentMapping + +from zope.event import notify +from zope.i18n import translate +from zope.interface import implements, implementer, Interface +from zope.component import adapts, adapter, getMultiAdapter, getAdapter, getAdapters +from zope.annotation.interfaces import IAnnotations + +from Products.CMFCore.utils import getToolByName +from Products.CMFPlone.Portal import PloneSite + +from pcommerce.core import events +from pcommerce.core.config import INITIALIZED, SENT, CANCELED, FAILED, PROCESSED +from pcommerce.core.currency import CurrencyAware +from pcommerce.core.cart import Cart +from pcommerce.core import interfaces +from pcommerce.core import PCommerceMessageFactory as _ + +ANNOTATIONS_KEY_ORDERS = 'pcommerce.core.orders' +ORDER_SESSION_KEY = 'pcommerce.orderid' +CART_SESSION_KEY = 'pcommerce.core.cart' + +class Order(Persistent): + """""" + implements(interfaces.IOrder) + + state = INITIALIZED + processed_steps = () + orderid = '' + userid = '' + products = None + date = None + price = 0.0 + currency = '' + zone = None + address = None + shipmentids = None + shipmentdata = None + paymentid = None + paymentdata = None + pretaxcharges = None + posttaxcharges = None + _taxincl = None + + def __init__(self, + orderid, + userid, + price=0.0, + currency='', + date=None, + zone=None, + address=None, + products=[], + shipmentids={}, + shipmentdata={}, + paymentid=None, + paymentdata=None, + pretaxcharges=(), + posttaxcharges=(), + taxincl=None): + """""" + self.orderid = orderid + self.userid = userid + self.price = price + self.currency = currency + self.date = date + self.zone = zone + self.address = address + self.products = products + self.shipmentids = shipmentids + self.shipmentdata = shipmentdata + self.paymentid = paymentid + self.paymentdata = paymentdata + self.pretaxcharges = pretaxcharges + self.posttaxcharges = posttaxcharges + self._taxincl = taxincl + + @property + def tax(self): + if self.zone is None: + return 0 + return self.zone[1][0] + + @property + def taxname(self): + if self.zone is None: + return None + return self.zone[1][1] + + @property + def taxincl(self): + if self._taxincl is None: + return 0 + return self._taxincl[0] + + @property + def taxinclname(self): + if self._taxincl is None: + return None + return self._taxincl[1] + + @property + def zonename(self): + if self.zone is None: + return None + return self.zone[0] + + @property + def pretaxcharge(self): + charge = 0 + for data in self.shipmentdata.values(): + charge += getattr(data, 'pretaxcharge', 0) + charge += getattr(self.paymentdata, 'pretaxcharge', 0) + for data in self.pretaxcharges: + charge += getattr(data, 'price', 0) + return charge + + @property + def posttaxcharge(self): + charge = 0 + for data in self.shipmentdata.values(): + charge += getattr(data, 'posttaxcharge', 0) + charge += getattr(self.paymentdata, 'posttaxcharge', 0) + for data in self.posttaxcharges: + charge += getattr(data, 'price', 0) + return charge + + @property + def subtotal(self): + return self.price + self.pretaxcharge + + @property + def pricetax(self): + return self.subtotal * self.tax / 100 + + @property + def pricetaxincl(self): + return self.subtotal / 100 * self.taxincl + + @property + def total(self): + return self.subtotal + self.pricetax + + @property + def totalincl(self): + return self.total + self.posttaxcharge + +class OrderRegistry(Cart): + """""" + implements(interfaces.IOrderRegistry) + adapts(Interface) + + def __init__(self, context): + self.context = context + self.portal = context + if not isinstance(context, PloneSite): + self.portal = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').portal() + + @property + def _items(self): + annotations = IAnnotations(self.portal) + items = annotations.get(ANNOTATIONS_KEY_ORDERS, OOBTree()) + # BBB + if not isinstance(items, OOBTree): + btree_items = OOBTree() + for key, value in items: + btree_items[key] = value + items = btree_items + return items + + def getOrders(self): + """ returns a list of orders + """ + return self._items + + def getOrder(self, orderid): + """ returns a order by its id + """ + if not self.has_key(orderid): + return None + return self[orderid] + + def create(self, order): + """ generates an order from the cart + """ + member = getMultiAdapter((self.context, self.context.REQUEST), name=u'plone_portal_state').member() + cart = interfaces.IShoppingCart(self.context) + if not len(cart): + return + order.userid = member.getId() + order.date = time() + order.currency = CurrencyAware(0).getCurrencySymbol() + products = cart.getProducts() + order_products = PersistentList() + price = 0 + for product in products: + price += product['price_raw'] * product['amount'] + order_products.append((product['uid'], + product['no'], + product['title'], + product['amount'], + product['price_raw'], + [(variation['uid'], variation['type'], variation['name']) for variation in product['variations']])) + if order_products != order.products: + order.processed_steps = () + order.products = order_products + order.price = price + + order._taxincl = interfaces.ITaxes(self.context).taxincl + + pretaxcharges = [] + providers = getAdapters((self.context,), interfaces.IPreTaxCharge) + for name, provider in providers: + pretaxcharges.append(provider.process(order)) + order.pretaxcharges = tuple(pretaxcharges) + + posttaxcharges = [] + providers = getAdapters((self.context,), interfaces.IPostTaxCharge) + for name, provider in providers: + posttaxcharges.append(provider.process(order)) + order.posttaxcharges = tuple(posttaxcharges) + + self[order.orderid] = order + + def recover(self, orderid): + """ recover an order from the registry + """ + if not self.has_key(orderid): + return + order = self[orderid] + cart = interfaces.IShoppingCart(self.context) + cart.clear() + for uid, title, price_raw, amount, variations in order.products: + if variations: + cart.addVariation([uid for uid, type, name in variations], amount) + else: + cart.add(uid, amount) + + notify(events.OrderRecoveredEvent(self, order)) + + def send(self, orderid, lang=None): + """ sends an order + """ + request = self.context.REQUEST + if not self.has_key(orderid): + return + order = self[orderid] + if order.state >= SENT: + if order.orderid == request.SESSION.get(ORDER_SESSION_KEY, 0): + request.SESSION.set(ORDER_SESSION_KEY, None) + return + portal_state = getMultiAdapter((self.context, request), name=u'plone_portal_state') + address = order.address + shipments = [] + shipments_customer = [] + product_shipment = {} + id_shipment = {} + i = 1 + for shipmentid, products in order.shipmentids.items(): + shipment = getAdapter(self.context, name=shipmentid, interface=interfaces.IShipmentMethod) + info = translate(shipment.mailInfo(order), context=request, target_language=lang) + if len(order.shipmentids) > 1: + info = '(%s) %s' % (i, info) + shipments.append(info) + + info_customer = translate(shipment.mailInfo(order, lang, customer=True), context=request, target_language=lang) + if len(order.shipmentids) > 1: + info = '(%s) %s' % (i, info_customer) + shipments_customer.append(info_customer) + + for product in products: + product_shipment[product] = i + id_shipment[shipmentid] = {'title': shipment.title, + 'number': i} + i += 1 + + payment = getAdapter(self.context, name=order.paymentid, interface=interfaces.IPaymentMethod) + alignment = Alignment() + + cart = [] + cart.append([translate(_('Product'), context=request, target_language=lang), + translate(_('Amount'), context=request, target_language=lang), + translate(_('Price'), context=request, target_language=lang), + translate(_('Price total'), context=request, target_language=lang)]) + cart.extend(['-', '']) + + for product in order.products: + cart.append([len(order.shipmentids) > 1 and '%s (%s)' % (product[1], product_shipment[product[0]]) or product[1], + str(product[3]), + ">"+CurrencyAware(product[4]).valueToString(order.currency), + ">"+CurrencyAware(product[4] * product[3]).valueToString(order.currency)]) + cart.append(product[2].decode('utf-8')) + for variation in product[5]: + cart.append("\t%s: %s" % (variation[1].decode('utf-8'), variation[2].decode('utf-8'))) + cart.append("") + + cart.append('-') + cart.append(['%s:' % translate(_('Total'), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.price).valueToString(order.currency)]) + cart.extend(['-', '']) + + if order.pretaxcharge: + if order.paymentdata.pretaxcharge: + cart.append(['%s:' % translate(payment.title, context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.paymentdata.pretaxcharge).valueToString(order.currency)]) + for shipmentid, data in order.shipmentdata.items(): + if data.pretaxcharge: + cart.append(['%s:' % (len(order.shipmentids) > 1 and '%s (%s)' % (translate(id_shipment[shipmentid]['title'], context=request, target_language=lang), id_shipment[shipmentid]['number']) or translate(id_shipment[shipmentid]['title'], context=request, target_language=lang)), '', '', + ">"+CurrencyAware(data.pretaxcharge).valueToString(order.currency)]) + for charge in order.pretaxcharges: + if charge.price: + cart.append(['%s:' % translate(charge.title, context=request, target_language=lang), '', '', + ">"+CurrencyAware(charge.price).valueToString(order.currency)]) + cart.append('-') + cart.append(['%s:' % translate(_('Total incl. charges'), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.subtotal).valueToString(order.currency)]) + cart.extend(['-', '']) + + if order.tax: + cart.append([order.taxname, '', '', + '%(pricetax)s (%(tax)s %% - %(zone)s)' % dict(tax=order.tax, + pricetax=">"+CurrencyAware(order.pricetax).valueToString(order.currency), + zone=address.zone)]) + cart.append('-') + cart.append(['%s:' % translate(_('Total incl. ${taxname}', mapping=dict(taxname=order.taxname)), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.total).valueToString(order.currency)]) + cart.extend(['-', '']) + + if order.taxincl and order.posttaxcharge is None: + cart.append([order.taxname, '', '', + '%(pricetax)s (%(tax)s %% - %(zone)s)' % dict(tax=order.tax, + pricetax=">"+CurrencyAware(order.pricetax).valueToString(order.currency), + zone=address.zone)]) + cart.append('-') + cart.append(['%s:' % translate(_('Total incl. ${tax}% ${taxname}', mapping=dict(tax=order.taxincl, taxname=order.taxinclname)), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) + cart.extend(['-', '']) + + + if order.posttaxcharge: + if order.paymentdata.posttaxcharge: + cart.append(['%s:' % translate(payment.title, context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.paymentdata.posttaxcharge).valueToString(order.currency)]) + for shipmentid, data in order.shipmentdata.items(): + if data.posttaxcharge: + cart.append(['%s:' % (len(order.shipmentids) > 1 and '%s (%s)' % (translate(id_shipment[shipmentid]['title'], context=request, target_language=lang), id_shipment[shipmentid]['number']) or translate(id_shipment[shipmentid]['title'], context=request, target_language=lang)), '', '', + ">"+CurrencyAware(data.posttaxcharge).valueToString(order.currency)]) + for charge in order.posttaxcharges: + if charge.price: + cart.append(['%s:' % translate(charge.title, context=request, target_language=lang), '', '', + ">"+CurrencyAware(charge.price).valueToString(order.currency)]) + cart.append('-') + if order.tax: + cart.append(['%s:' % translate(_('Total incl. charges and ${taxname}', mapping=dict(taxname=order.taxname)), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) + elif order.taxincl: + cart.append(['%s:' % translate(_('Total incl. charges and ${tax}% ${taxname}', mapping=dict(tax=order.taxincl, taxname=order.taxinclname)), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) + else: + cart.append(['%s:' % translate(_('Total incl. charges'), context=request, target_language=lang), '', '', + ">"+CurrencyAware(order.totalincl).valueToString(order.currency)]) + cart.extend(['-', '']) + + alignment.extend(cart) + + # do alignment + cart = alignment.alignItems(cart) + + email_from = getToolByName(self.context, 'portal_properties').pcommerce_properties.getProperty('email_address', '') + if not email_from: + email_from = portal_state.portal().getProperty('email_from_address', '') + email_from_name = portal_state.portal().getProperty('email_from_name', '') + mapping = {'orderid': order.orderid, + 'shipments': '\n\n'.join(shipments), + 'payment': translate(payment.mailInfo(order, lang), context=request, target_language=lang), + 'cart': '\n'.join(cart), + 'currency': order.currency, + 'address': address.mailInfo(request, lang), + 'name': address.firstname +' '+ address.lastname, + 'from_name': email_from_name, + 'from_email': email_from} + + mailhost = getToolByName(self.context, 'MailHost') + mailhost.secureSend(translate(self.getMessage(mapping), context=request, target_language=lang), + mto=email_from, + mfrom='%s <%s>' % (address.firstname +' '+ address.lastname, address.email), + subject=translate(_('email_order_title', default='New order [${orderid}]', mapping={'orderid': order.orderid}), context=request, target_language=lang), + charset='utf-8') + + mapping.update({'shipments': '\n\n'.join(shipments_customer), + 'payment': translate(payment.mailInfo(order, lang, customer=True), context=request, target_language=lang), + 'address': address.mailInfo(request, lang, True)}) + mailhost.secureSend(translate(self.getMessageCustomer(mapping), context=request, target_language=lang), + mto='%s <%s>' % (address.firstname +' '+ address.lastname, address.email), + mfrom='%s <%s>' % (email_from_name, email_from), + subject=translate(_('email_customer_title', default='Confirmation e-mail'), context=request, target_language=lang), + charset='utf-8') + + notify(events.OrderSentEvent(self, order)) + + order.state = SENT + if order.orderid == request.SESSION.get(ORDER_SESSION_KEY, 0): + request.SESSION.set(ORDER_SESSION_KEY, None) + + def process(self, orderid): + """ process an order + """ + if not self.has_key(orderid): + return + order = self[orderid] + + notify(events.OrderProcessedEvent(self, order)) + + order.state = PROCESSED + if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): + self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) + + # clear the shopping cart + self.context.REQUEST.SESSION.set(CART_SESSION_KEY, None) + + def cancel(self, orderid): + """ cancel an order + """ + if not self.has_key(orderid): + return + order = self[orderid] + + notify(events.OrderCanceledEvent(self, order)) + + order.state = CANCELED + if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): + self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) + + def fail(self, orderid): + """ fail an order + """ + if not self.has_key(orderid): + return + order = self[orderid] + + notify(events.OrderFailedEvent(self, order)) + + order.state = FAILED + if order.orderid == self.context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0): + self.context.REQUEST.SESSION.set(ORDER_SESSION_KEY, None) + + def getMessage(self, mapping): + return _('email_order_body', default=\ +"""New order by ${name} + +Orderid: ${orderid} + +${cart} +Currency: ${currency} + + +Address: +${address} + +Payment: +${payment} + +Shipment: +${shipments} + +""", mapping=mapping) + + def getMessageCustomer(self, mapping): + return _('email_customer_body', default=\ +"""Dear ${name} + +Your order has been successfully registered. Please find a complete +overview of your order below. + +Order ID: ${orderid} + +${cart} +Currency: ${currency} + + +Address: +${address} + +Payment: +${payment} + +Shipment: +${shipments} + + +If you have any questions concerning your purchase do not hesitate +to contact us at ${from_email}. + +Best regards + +${from_name}""", mapping=mapping) + + def _save(self): + annotations = IAnnotations(self.portal) + annotations[ANNOTATIONS_KEY_ORDERS] = self._items + +class Alignment(object): + + separate = 4 + rows = [] + + def align(self, item): + if not isinstance(item, list): + if item.startswith('-'): + return '-' * len(self) + return item + aligned = [] + for i in range(0, len(item)): + if item[i].startswith('>'): + item[i] = item[i][1:] + aligned.append((' ' * (self.max(i) - len(item[i]))) + item[i]) + else: + aligned.append(item[i] + (' ' * (self.max(i) - len(item[i])))) + return (' ' * self.separate).join(aligned) + + def alignItems(self, items): + return [self.align(item) for item in items] + + def append(self, item): + self.rows.append(item) + + def extend(self, items): + self.rows.extend(items) + + def max(self, i): + return max([len(row[i]) for row in self.rows if isinstance(row, list) and len(row) > i]) + + def __len__(self): + l = 0 + for i in range(0, max([len(row) for row in self.rows if isinstance(row, list)])): + l += self.max(i) + l += i * self.separate + return l + +@adapter(Interface) +@implementer(interfaces.IOrder) +def get_order(context): + orderid = context.REQUEST.SESSION.get(ORDER_SESSION_KEY, 0) + order = None + orders = interfaces.IOrderRegistry(context) + if orderid and orders.has_key(orderid): + order = orders[orderid] + if order.state is INITIALIZED: + notify(events.OrderAboutToBeRecreatedEvent(orders, order)) + orders.create(order) + notify(events.OrderRecreatedEvent(orders, order)) + else: + order = None + + if not order: + orderid = int(time()*100) + context.REQUEST.SESSION.set(ORDER_SESSION_KEY, orderid) + order = Order(orderid, None) + orders.create(order) + + notify(events.OrderCreatedEvent(orders, order)) + + return order diff --git a/src/pcommerce/core/permissions.zcml b/src/pcommerce/core/permissions.zcml new file mode 100644 index 0000000..a6615a1 --- /dev/null +++ b/src/pcommerce/core/permissions.zcml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/plone3.py b/src/pcommerce/core/plone3.py new file mode 100644 index 0000000..dc115a5 --- /dev/null +++ b/src/pcommerce/core/plone3.py @@ -0,0 +1,2 @@ +from Products.PlacelessTranslationService.utility import PTSTranslationDomain +pcommercedomain = PTSTranslationDomain('pcommerce') \ No newline at end of file diff --git a/src/pcommerce/core/processor.py b/src/pcommerce/core/processor.py new file mode 100644 index 0000000..c42537a --- /dev/null +++ b/src/pcommerce/core/processor.py @@ -0,0 +1,35 @@ +from zope.interface import implements, Interface +from zope.component import adapts, getAdapter +from zope.event import notify + +from pcommerce.core import interfaces +from pcommerce.core.config import FAILED, PROCESSED, SENT +from pcommerce.core.events import OrderProcessingSuccessfulEvent, OrderProcessingFailedEvent + +class PaymentProcessor(object): + """""" + implements(interfaces.IPaymentProcessor) + adapts(Interface) + + def __init__(self, context): + self.context = context + + def processOrder(self, orderid, paymentid, lang=None): + orderid = int(orderid) + registry = interfaces.IOrderRegistry(self.context) + order = registry.getOrder(orderid) + if not order or not order.paymentid == paymentid: + return 'no matching order found' + if order.state is not PROCESSED and order.state is not FAILED: + method = getAdapter(self.context, name=paymentid, interface=interfaces.IPaymentMethod) + if method.verifyPayment(order): + if order.state < SENT: + registry.send(orderid, lang=None) + registry.process(orderid) + notify(OrderProcessingSuccessfulEvent(registry, order)) + return 'payment successfully processed' + else: + registry.fail(orderid) + notify(OrderProcessingFailedEvent(registry, order)) + return 'processing payment failed' + return 'payment already processed' diff --git a/src/pcommerce/core/profiles/default/.propertiestool.xml.swp b/src/pcommerce/core/profiles/default/.propertiestool.xml.swp new file mode 100644 index 0000000000000000000000000000000000000000..cf1aea79132cb11ea65b595080fa8cbb3bd3e0d6 GIT binary patch literal 12288 zcmeI2!EVz)5Qe9S0|E-D@BpqkaH^d)DsV{CLnI^)NR<$9!?M?#WLxj9wO+SL4!{%e z3P`*McU}O*ky9&iD6hacc1p3@)X;K3%u2u3yITL=`RrLK%0#W_kDoXXyf$FF1@PkV z`_`4Em(aTgFwl}uiup6zM9WBwq}MmXPP|BuPFeqIYUsy&*H1+~_rpA~erj~ejTJnzS|{E}CZ{}>rilO%$Zdb+;Ucux zR$B#(yY8}cd+8Z*Ap%5z2oM1xKm>>Y5g-CY;6EZ@(*<~q@m{K8zEkxJwZ0lsM+Arf z5g-CYfCvx)B0vO)01+SpM1TnVg9O4DVEZb-XH@b3|Lphwx0?VTQSVSa)WHpa_o%0+ z%cu{F00wmr_2oLi8`L^#AL|C*qB^KU^!!?Re=7W`5dk7V1c(3;AOb{y2oQn4LZIX8 zXqz+J1qa)&qv=dlJUVt%DEWqKbgp8d1_9&BX0Bt$Db5OIT_?@W0Iwf~NygpodS_O5 zIxf9Wa7b$AT9a)SUQ8#sRPz`% zvO3OisO?2Y+|cfRlZXqivm}mO8=f7#(99Z4lzLt?2{6?e z!Wwe6qjOBGGROYhZeZE@O%zs|4+L%^v_h*uo0yxKYlLOxJXG~irzb(9c*`U$PMDeH z$OH{4aP + + + + Manage orders + List of all orders and their statuses + string:${globals_view/navigationRootUrl}/@@manage-orders + + python:member is not None + + + + True + + + diff --git a/src/pcommerce/core/profiles/default/catalog.xml b/src/pcommerce/core/profiles/default/catalog.xml new file mode 100644 index 0000000..cf847a2 --- /dev/null +++ b/src/pcommerce/core/profiles/default/catalog.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/profiles/default/controlpanel.xml b/src/pcommerce/core/profiles/default/controlpanel.xml new file mode 100644 index 0000000..bd743c0 --- /dev/null +++ b/src/pcommerce/core/profiles/default/controlpanel.xml @@ -0,0 +1,19 @@ + + + + + Manage portal + + + diff --git a/src/pcommerce/core/profiles/default/cssregistry.xml b/src/pcommerce/core/profiles/default/cssregistry.xml new file mode 100644 index 0000000..3804ac7 --- /dev/null +++ b/src/pcommerce/core/profiles/default/cssregistry.xml @@ -0,0 +1,6 @@ + + + + diff --git a/src/pcommerce/core/profiles/default/factorytool.xml b/src/pcommerce/core/profiles/default/factorytool.xml new file mode 100644 index 0000000..618b266 --- /dev/null +++ b/src/pcommerce/core/profiles/default/factorytool.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/pcommerce/core/profiles/default/jsregistry.xml b/src/pcommerce/core/profiles/default/jsregistry.xml new file mode 100644 index 0000000..2db2b1a --- /dev/null +++ b/src/pcommerce/core/profiles/default/jsregistry.xml @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/src/pcommerce/core/profiles/default/metadata.xml b/src/pcommerce/core/profiles/default/metadata.xml new file mode 100644 index 0000000..9a5dd3c --- /dev/null +++ b/src/pcommerce/core/profiles/default/metadata.xml @@ -0,0 +1,7 @@ + + + 10 + + profile-Products.SingleKeywordWidget:default + + diff --git a/src/pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt b/src/pcommerce/core/profiles/default/pcommerce.core_migrate05a105a2.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/profiles/default/portlets.xml b/src/pcommerce/core/profiles/default/portlets.xml new file mode 100644 index 0000000..1417286 --- /dev/null +++ b/src/pcommerce/core/profiles/default/portlets.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/propertiestool.xml b/src/pcommerce/core/profiles/default/propertiestool.xml new file mode 100644 index 0000000..1b19908 --- /dev/null +++ b/src/pcommerce/core/profiles/default/propertiestool.xml @@ -0,0 +1,20 @@ + + + + PCommerce order + False + + + + 3 + 0 + 3 + 6 + 0 + 2 + 2 + 0 + 0 + 5 + + diff --git a/src/pcommerce/core/profiles/default/rolemap.xml b/src/pcommerce/core/profiles/default/rolemap.xml new file mode 100644 index 0000000..f328596 --- /dev/null +++ b/src/pcommerce/core/profiles/default/rolemap.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/skins.xml b/src/pcommerce/core/profiles/default/skins.xml new file mode 100644 index 0000000..a76d3e3 --- /dev/null +++ b/src/pcommerce/core/profiles/default/skins.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/pcommerce/core/profiles/default/types.xml b/src/pcommerce/core/profiles/default/types.xml new file mode 100644 index 0000000..b5a6987 --- /dev/null +++ b/src/pcommerce/core/profiles/default/types.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/types/Folder.xml b/src/pcommerce/core/profiles/default/types/Folder.xml new file mode 100644 index 0000000..484795b --- /dev/null +++ b/src/pcommerce/core/profiles/default/types/Folder.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/types/Price.xml b/src/pcommerce/core/profiles/default/types/Price.xml new file mode 100644 index 0000000..c578c7a --- /dev/null +++ b/src/pcommerce/core/profiles/default/types/Price.xml @@ -0,0 +1,27 @@ + + + Price + A price + ++resource++price_icon.gif + Price + pcommerce.core + addPrice + view + False + True + + False + + + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/types/Product.xml b/src/pcommerce/core/profiles/default/types/Product.xml new file mode 100644 index 0000000..7c38820 --- /dev/null +++ b/src/pcommerce/core/profiles/default/types/Product.xml @@ -0,0 +1,44 @@ + + + Product + A product + ++resource++product_icon.gif + Product + pcommerce.core + addProduct + view + True + True + view + + + + + + False + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/types/Variation.xml b/src/pcommerce/core/profiles/default/types/Variation.xml new file mode 100644 index 0000000..63cd229 --- /dev/null +++ b/src/pcommerce/core/profiles/default/types/Variation.xml @@ -0,0 +1,43 @@ + + + Variation + A variation of a product + ++resource++variation_icon.gif + Variation + pcommerce.core + addVariation + view + False + True + view + + + + + False + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pcommerce/core/profiles/default/viewlets.xml b/src/pcommerce/core/profiles/default/viewlets.xml new file mode 100644 index 0000000..2ab9d3e --- /dev/null +++ b/src/pcommerce/core/profiles/default/viewlets.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/pcommerce/core/registry.py b/src/pcommerce/core/registry.py new file mode 100644 index 0000000..cf383d2 --- /dev/null +++ b/src/pcommerce/core/registry.py @@ -0,0 +1,28 @@ +from zope.interface import implements, Interface +from zope.component import adapts, getAdapters + +from pcommerce.core import interfaces + +class Shipment(object): + """shipment-registry""" + implements(interfaces.IShipmentRegistry) + adapts(Interface) + + def __init__(self, context): + self.context = context + + def getShipmentMethods(self): + """get all registered shipment-methods""" + return dict([(name, adapter) for name, adapter in getAdapters((self.context,), interfaces.IShipmentMethod)]) + +class Payment(object): + """payment-registry""" + implements(interfaces.IPaymentRegistry) + adapts(Interface) + + def __init__(self, context): + self.context = context + + def getPaymentMethods(self): + """get all registered payment-methods""" + return dict([(name, adapter) for name, adapter in getAdapters((self.context,), interfaces.IPaymentMethod)]) diff --git a/src/pcommerce/core/required.py b/src/pcommerce/core/required.py new file mode 100644 index 0000000..27a90d6 --- /dev/null +++ b/src/pcommerce/core/required.py @@ -0,0 +1,9 @@ +from zope.interface import implementer, Interface +from zope.component import adapter + +from pcommerce.core.interfaces import IRequiredComponents + +@adapter(Interface) +@implementer(IRequiredComponents) +def components(context): + return ('address', 'shipments', 'shipment', 'payments', 'payment', 'overview', 'gtc',) diff --git a/src/pcommerce/core/setuphandlers.py b/src/pcommerce/core/setuphandlers.py new file mode 100644 index 0000000..62cb69a --- /dev/null +++ b/src/pcommerce/core/setuphandlers.py @@ -0,0 +1,19 @@ +from pcommerce.core.interfaces import IOrderRegistry + +def migrate05a105a2(context): + + if context.readDataFile('pcommerce.core_migrate05a105a2.txt') is None: + return + + portal = context.getSite() + + registry = IOrderRegistry(portal) + for order in registry.getOrders().itervalues(): + if hasattr(order.paymentdata, 'shipmentid'): + order.paymentdata.id = order.paymentdata.shipmentid + delattr(order.paymentdata, 'shipmentid') + for data in order.shipmentdata.values(): + if hasattr(data, 'shipmentid'): + data.id = data.shipmentid + delattr(data, 'shipmentid') + \ No newline at end of file diff --git a/src/pcommerce/core/skins/pcommerce/pcommerce.css.dtml b/src/pcommerce/core/skins/pcommerce/pcommerce.css.dtml new file mode 100644 index 0000000..e7fef27 --- /dev/null +++ b/src/pcommerce/core/skins/pcommerce/pcommerce.css.dtml @@ -0,0 +1,530 @@ +/* (do not remove this :) */ +/* (not this either :) */ + +/* shopping cart portlet */ + +.portletShoppingCart .portletItem { + font-size:90%; +} + +.portletShoppingCart .portletItem dt { + clear:left; + float:left; + width:60%; + font-weight:normal; + background-color:transparent; + padding-top:0; + padding-bottom:0; + line-height:2em; +} + +.portletShoppingCart .portletItem dd { + padding:0; + margin:0; + font-weight:bold; + line-height:2em; +} + +.portletShoppingCart .portletFooter { + clear:both; +} + +.portletShoppingCart .portletFooter a { + font-weight:bold; +} + + +/* shopping cart */ + +#cart .formControls { + text-align:right; +} + +#cart table { + position:relative; + border:none; + padding:0; + margin:0 0 1em 0; + border-collapse: collapse; +} + +#cart table th, +#cart table td { + vertical-align:baseline; + margin:0; + padding:0.5em 1em; + white-space:nowrap; + border-width:0 0 &dtml-borderWidth; 0; + border-style:&dtml-borderStyle;; + border-color:&dtml-globalBorderColor;; +} + +#cart table .info { + text-align:left; + width:100%; + white-space:normal; +} + +#cart table .amount { + text-align:center; +} + +#cart table .price { + text-align:right; +} + +#cart table tfoot td, +#cart table tfoot th { + background-color:&dtml-globalBackgroundColor;; +} + +#cart table tr.discreet th, +#cart table tr.discreet td { + background-color: &dtml-evenRowBackgroundColor;; + padding-top:0.2em; + padding-bottom:0.2em; +} + +#cart .formControls input.standalone { + background-image:none; + padding:1px; +} + +#cart .formControls input.context { + padding:1px 8px 1px 1px; + background-image:url("arrowRight.gif"); + background-position:right center; + background-repeat:no-repeat; +} + + +/* checkout */ + +#checkout .component { + margin:1em 0; + padding:1em; + border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; +} + +#checkout .component h2 { + margin:0 0 1em 0; + font-size:1.2em; +} + +#checkout .formControls { + clear:both; + text-align:center; + height:2em; + position:relative; +} + +#checkout .formControls input { + background-image:none; + padding:1px; +} + +#checkout .formControls .next { + display:block; + position:absolute; + right:0; + padding-right:8px; + background-image:url("arrowRight.gif"); + background-position:right center; + background-repeat:no-repeat; +} + +#checkout .formControls .previous { + position:absolute; + left:0; + padding-left:8px; + background-image:url("arrowLeft.gif"); + background-position:left center; + background-repeat:no-repeat; +} + +#checkout .formControls .checkout { + padding-right:12px; + background-image:url("arrowRightmost.gif"); + background-repeat:no-repeat; +} + +#checkout .field { + clear:both; + position:relative; + margin-right:0; +} + +#checkout .component input, +#checkout .component textarea { + width:95%; +} + +#checkout .component input.noborder { + width:auto; +} + +#checkout .field.error { + width:auto; +} + +#checkout .address .field label { + float:left; + width:120px; + margin-bottom:0.5em; +} + +#checkout .address .field .widget { + margin:0 10px 0 120px; +} + +* html #checkout .address .field .widget, +*+html #checkout .address .field .widget { + float:left; + margin:0; +} + +#checkout .address .field .fieldRequired { + position:absolute; + right:0; + width:1px; + overflow:hidden; +} + +#checkout .address .field .zip_city_wrap { + width:95%; + left:0; +} + +#checkout .address .field .zip { + display:inline; + width:10%; + margin:0; +} + +#checkout .address .field .city { + display:inline; + width:87%; + margin: 0 -2px 0 0; + float: right; +} + +#checkout .steps { + position: relative; + text-align: center; + margin-top:1em; +} + +#checkout .steps .step { + display:inline; + padding: 0.5em; + text-decoration: none; + border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; +} + +* html #checkout .steps .step, +*+html #checkout .steps .step { + margin:0 0.2em; +} + +#checkout .steps .step.select { + background-color:&dtml-globalBackgroundColor;; +} + +#checkout .description { + margin:0; +} + +#checkout ul.products { + margin-top:0; + margin-bottom:1em; + font-size:0.9em; +} + +#checkout #shipment .shipment { + margin:0 0 2em 0; +} + +#checkout ul.selection li { + padding:0; + margin:0; + display:block; +} + +#checkout ul.selection label { + display:block; + padding:0.5em; + font-weight:normal; + line-height:1.2em; +} + +#checkout ul.selection label:hover { + cursor:pointer; + background-color:&dtml-globalBackgroundColor;; +} + +#checkout ul.selection label input { + float:left; + display:block; + margin:0 1em 0 0; +} + +#checkout ul.selection label img, +#checkout .logo { + display:block; + float:right; + margin:0 0 0 1em; + border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; +} + +#checkout .logo { + margin-bottom:1em; +} + +#checkout ul.selection label strong, +#checkout ul.selection label span { + display:block; + margin-left:3em; +} + +#checkout .overview { + position:relative; + width:100%; +} + +#checkout .overview .box { + float:left; + width:27%; + border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; + margin:0 3% 0 0; + padding:2%; + overflow:hidden; +} + +#checkout .overview .box h3 { + font-size:1.1em; + font-weight:bold; + margin:0; + border:none; +} + +#checkout .overview .box h4 { + font-size:1em; + font-weight:bold; +} + +#checkout .overview .box .shipmentinfo { + margin-bottom:1em; +} + +#checkout .overview .shipment { + margin-right:0; +} + +#checkout .overview .payment { + float:right; + margin-right:0; +} + +#checkout #cart { + margin:1em 0; +} + + +/* product view */ + +.productInfo a { + display:block; + margin:0 0 0 40px; +} + +.productInfo .no { + display:block; + font-size:90%; + margin:0 0 0.5em 40px; +} + +.productInfo .productImage { + float:left; + margin:0; +} + +.productInfo dl { + clear:both; + font-size:90%; + margin:0 0 0 40px; + padding:0; + line-height:normal; +} + +.productInfo dl dt { + display:block; + float:left; + clear:left; + width:70px; + padding:0; + margin:0; + line-height:normal; +} + +.productInfo dl dd { + display:block; + padding:0; + margin:0 0 0 75px; + line-height:normal; +} + +.addLink { + display:block; + float:right; + font-size:90%; + text-decoration:none; + margin:1.4em 0.5em 0 0; + padding:0 0.5em; + background-color:&dtml-backgroundColor;; +} + +.portletInfoBox { + float:right; + margin:0 0 1em 1em; +} + +* html .portletInfoBox { + width:1%; +} + +.portletInfoBox .portletItem { + border-top:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; +} + +.portletInfoBox .portletItem img { + display:block; +} + +.priceInfo { + font-size:90%; +} + +.buyViewlet { + clear:both; + background-color:&dtml-globalBackgroundColor;; + border:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; + margin:1em 0 2em 0; +} + +.buyViewlet form { + clear:both; + padding:0.8em 1em; +} + +.buyViewlet input, +.buyViewlet select, +.buyViewlet label { + margin:0 0.5em 0.5em 0; + display:block; + float:left; +} + +.buyViewlet .context { + background-color:&dtml-backgroundColor;; + background-image:none; + padding-left:1px; +} + +.buyViewlet label { + clear:left; + font-size:90%; + color:&dtml-linkColor;; + line-height:1.4em; +} + +.productList { + position:relative; + clear:both; + margin:4em 0; +} + +.productList .list { + position:relative; + margin:0 0 1em 0; +} + +.new .list { + margin-right:0; +} + +.portletProduct { + width:30.5%; + float:left; + margin-right:2%; +} + +.portletProduct.col3, +* html .portletProduct.col3 { + float:right; + margin-right:0; +} + +.new .portletProduct { + width:48%; + margin-right:0; +} + +.portletProduct.col1 { + clear:both; +} + +.new .portletProduct.col2 { + float:right; +} + +.portletProduct .portletItem { + border-top:&dtml-borderWidth; &dtml-borderStyle; &dtml-globalBorderColor;; +} + +.portletProduct .portletItem a, +.portletProduct .description { + border-bottom:none; + display:block; +} + +.portletProduct .portletItem a.image { + margin-bottom:0.5em; +} + +.portletProduct .priceInfo { + font-size:100%; +} + + +/* configlet */ + +#pcommerce_configlet table th { + text-align:left; +} + +.clearfix:after, +.component:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix, +.component { + display: inline-block; +} + +html[xmlns] .clearfix, +html[xmlns] .component { + display: block; +} + +* html .clearfix, +* html .component { + height: 1%; +} + +/* */ \ No newline at end of file diff --git a/src/pcommerce/core/steps.py b/src/pcommerce/core/steps.py new file mode 100644 index 0000000..f51c547 --- /dev/null +++ b/src/pcommerce/core/steps.py @@ -0,0 +1,16 @@ +from zope.interface import implementer, Interface +from zope.component import adapter + +from pcommerce.core.interfaces import ISteps +from pcommerce.core import PCommerceMessageFactory as _ + +@adapter(Interface) +@implementer(ISteps) +def steps(context): + return ({'name':_('Address'), 'components':('address',)}, + {'name':_('Shipment'), 'components':('shipments',)}, + {'name':_('Shipment'), 'components':('shipment',)}, + {'name':_('Payment'), 'components':('payments',)}, + {'name':_('Payment'), 'components':('payment',)}, + {'name':_('Overview'), 'components':('overview', 'gtc',)}, + {'name':_('Confirmation'), 'components':('confirmation',)}) \ No newline at end of file diff --git a/src/pcommerce/core/vocabulary.py b/src/pcommerce/core/vocabulary.py new file mode 100644 index 0000000..d9ae1c1 --- /dev/null +++ b/src/pcommerce/core/vocabulary.py @@ -0,0 +1,27 @@ +from zope.interface import implementer, implements +from zope.component import adapter, adapts +from zope.schema.interfaces import IVocabularyFactory +from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm + +from Products.Archetypes.interfaces import IFieldDefaultProvider + +from pcommerce.core.interfaces import IShipmentRegistry, IProduct + +@implementer(IVocabularyFactory) +def shipments(context): + shipments = [] + registry = IShipmentRegistry(context) + r_shipments = registry.getShipmentMethods() + for name, shipment in r_shipments.items(): + shipments.append(SimpleTerm(name, name, shipment.title)) + return SimpleVocabulary(shipments) + +class ShipmentsDefault(object): + implements(IFieldDefaultProvider) + adapts(IProduct) + def __init__(self, context): + self.context = context + def __call__(self): + vocabulary = shipments(self.context) + for term in vocabulary: + yield term.value From 1963559ab0f0556b391793926fe2a021117b5b20 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 12:46:52 +0100 Subject: [PATCH 03/27] buildout added --- bootstrap.py | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++ buildout.cfg | 35 +++++++ 2 files changed, 295 insertions(+) create mode 100644 bootstrap.py create mode 100644 buildout.cfg diff --git a/bootstrap.py b/bootstrap.py new file mode 100644 index 0000000..5f2cb08 --- /dev/null +++ b/bootstrap.py @@ -0,0 +1,260 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. +""" + +import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess +from optparse import OptionParser + +if sys.platform == 'win32': + def quote(c): + if ' ' in c: + return '"%s"' % c # work around spawn lamosity on windows + else: + return c +else: + quote = str + +# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. +stdout, stderr = subprocess.Popen( + [sys.executable, '-Sc', + 'try:\n' + ' import ConfigParser\n' + 'except ImportError:\n' + ' print 1\n' + 'else:\n' + ' print 0\n'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() +has_broken_dash_S = bool(int(stdout.strip())) + +# In order to be more robust in the face of system Pythons, we want to +# run without site-packages loaded. This is somewhat tricky, in +# particular because Python 2.6's distutils imports site, so starting +# with the -S flag is not sufficient. However, we'll start with that: +if not has_broken_dash_S and 'site' in sys.modules: + # We will restart with python -S. + args = sys.argv[:] + args[0:0] = [sys.executable, '-S'] + args = map(quote, args) + os.execv(sys.executable, args) +# Now we are running with -S. We'll get the clean sys.path, import site +# because distutils will do it later, and then reset the path and clean +# out any namespace packages from site-packages that might have been +# loaded by .pth files. +clean_path = sys.path[:] +import site +sys.path[:] = clean_path +for k, v in sys.modules.items(): + if k in ('setuptools', 'pkg_resources') or ( + hasattr(v, '__path__') and + len(v.__path__)==1 and + not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): + # This is a namespace package. Remove it. + sys.modules.pop(k) + +is_jython = sys.platform.startswith('java') + +setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' +distribute_source = 'http://python-distribute.org/distribute_setup.py' + +# parsing arguments +def normalize_to_url(option, opt_str, value, parser): + if value: + if '://' not in value: # It doesn't smell like a URL. + value = 'file://%s' % ( + urllib.pathname2url( + os.path.abspath(os.path.expanduser(value))),) + if opt_str == '--download-base' and not value.endswith('/'): + # Download base needs a trailing slash to make the world happy. + value += '/' + else: + value = None + name = opt_str[2:].replace('-', '_') + setattr(parser.values, name, value) + +usage = '''\ +[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] + +Bootstraps a buildout-based project. + +Simply run this script in a directory containing a buildout.cfg, using the +Python that you want bin/buildout to use. + +Note that by using --setup-source and --download-base to point to +local resources, you can keep this script from going over the network. +''' + +parser = OptionParser(usage=usage) +parser.add_option("-v", "--version", dest="version", + help="use a specific zc.buildout version") +parser.add_option("-d", "--distribute", + action="store_true", dest="use_distribute", default=False, + help="Use Distribute rather than Setuptools.") +parser.add_option("--setup-source", action="callback", dest="setup_source", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or file location for the setup file. " + "If you use Setuptools, this will default to " + + setuptools_source + "; if you use Distribute, this " + "will default to " + distribute_source +".")) +parser.add_option("--download-base", action="callback", dest="download_base", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or directory for downloading " + "zc.buildout and either Setuptools or Distribute. " + "Defaults to PyPI.")) +parser.add_option("--eggs", + help=("Specify a directory for storing eggs. Defaults to " + "a temporary directory that is deleted when the " + "bootstrap script completes.")) +parser.add_option("-t", "--accept-buildout-test-releases", + dest='accept_buildout_test_releases', + action="store_true", default=False, + help=("Normally, if you do not specify a --version, the " + "bootstrap script and buildout gets the newest " + "*final* versions of zc.buildout and its recipes and " + "extensions for you. If you use this flag, " + "bootstrap and buildout will get the newest releases " + "even if they are alphas or betas.")) +parser.add_option("-c", None, action="store", dest="config_file", + help=("Specify the path to the buildout configuration " + "file to be used.")) + +options, args = parser.parse_args() + +# if -c was provided, we push it back into args for buildout's main function +if options.config_file is not None: + args += ['-c', options.config_file] + +if options.eggs: + eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) +else: + eggs_dir = tempfile.mkdtemp() + +if options.setup_source is None: + if options.use_distribute: + options.setup_source = distribute_source + else: + options.setup_source = setuptools_source + +if options.accept_buildout_test_releases: + args.append('buildout:accept-buildout-test-releases=true') +args.append('bootstrap') + +try: + import pkg_resources + import setuptools # A flag. Sometimes pkg_resources is installed alone. + if not hasattr(pkg_resources, '_distribute'): + raise ImportError +except ImportError: + ez_code = urllib2.urlopen( + options.setup_source).read().replace('\r\n', '\n') + ez = {} + exec ez_code in ez + setup_args = dict(to_dir=eggs_dir, download_delay=0) + if options.download_base: + setup_args['download_base'] = options.download_base + if options.use_distribute: + setup_args['no_fake'] = True + ez['use_setuptools'](**setup_args) + if 'pkg_resources' in sys.modules: + reload(sys.modules['pkg_resources']) + import pkg_resources + # This does not (always?) update the default working set. We will + # do it. + for path in sys.path: + if path not in pkg_resources.working_set.entries: + pkg_resources.working_set.add_entry(path) + +cmd = [quote(sys.executable), + '-c', + quote('from setuptools.command.easy_install import main; main()'), + '-mqNxd', + quote(eggs_dir)] + +if not has_broken_dash_S: + cmd.insert(1, '-S') + +find_links = options.download_base +if not find_links: + find_links = os.environ.get('bootstrap-testing-find-links') +if find_links: + cmd.extend(['-f', quote(find_links)]) + +if options.use_distribute: + setup_requirement = 'distribute' +else: + setup_requirement = 'setuptools' +ws = pkg_resources.working_set +setup_requirement_path = ws.find( + pkg_resources.Requirement.parse(setup_requirement)).location +env = dict( + os.environ, + PYTHONPATH=setup_requirement_path) + +requirement = 'zc.buildout' +version = options.version +if version is None and not options.accept_buildout_test_releases: + # Figure out the most recent final version of zc.buildout. + import setuptools.package_index + _final_parts = '*final-', '*final' + def _final_version(parsed_version): + for part in parsed_version: + if (part[:1] == '*') and (part not in _final_parts): + return False + return True + index = setuptools.package_index.PackageIndex( + search_path=[setup_requirement_path]) + if find_links: + index.add_find_links((find_links,)) + req = pkg_resources.Requirement.parse(requirement) + if index.obtain(req) is not None: + best = [] + bestv = None + for dist in index[req.project_name]: + distv = dist.parsed_version + if _final_version(distv): + if bestv is None or distv > bestv: + best = [dist] + bestv = distv + elif distv == bestv: + best.append(dist) + if best: + best.sort() + version = best[-1].version +if version: + requirement = '=='.join((requirement, version)) +cmd.append(requirement) + +if is_jython: + import subprocess + exitcode = subprocess.Popen(cmd, env=env).wait() +else: # Windows prefers this, apparently; otherwise we would prefer subprocess + exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) +if exitcode != 0: + sys.stdout.flush() + sys.stderr.flush() + print ("An error occurred when trying to install zc.buildout. " + "Look above this message for any errors that " + "were output by easy_install.") + sys.exit(exitcode) + +ws.add_entry(eggs_dir) +ws.require(requirement) +import zc.buildout.buildout +zc.buildout.buildout.main(args) +if not options.eggs: # clean up temporary egg directory + shutil.rmtree(eggs_dir) diff --git a/buildout.cfg b/buildout.cfg new file mode 100644 index 0000000..1f8d641 --- /dev/null +++ b/buildout.cfg @@ -0,0 +1,35 @@ +[buildout] +parts = + instance + +extends = http://dist.plone.org/release/4.2.2/versions.cfg + +versions = versions +develop = . + +extensions = mr.developer + +sources = sources +auto-checkout = * +sources-dir = src-mrd +eggs = +zcml = + +[instance] +recipe = plone.recipe.zope2instance +user = admin:admin +http-address = 8088 +eggs = + ${buildout:eggs} + Plone + Pillow + pcommerce.core +environment-vars = + zope_i18n_compile_mo_files true + +zcml = + ${buildout:zcml} + +[sources] + +[versions] From 6a60afd96cfac2091d4c5a9b961a06c4d76ba037 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 14:15:54 +0100 Subject: [PATCH 04/27] First tests add & travis config --- .travis.yml | 8 ++++ buildout.cfg | 10 ++++- setup.py | 6 +++ src/pcommerce/core/testing.py | 40 ++++++++++++++++++++ src/pcommerce/core/tests/__init__.py | 0 src/pcommerce/core/tests/test_integration.py | 24 ++++++++++++ travis.cfg | 17 +++++++++ 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 .travis.yml create mode 100644 src/pcommerce/core/testing.py create mode 100644 src/pcommerce/core/tests/__init__.py create mode 100644 src/pcommerce/core/tests/test_integration.py create mode 100644 travis.cfg diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6d194c7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: python +python: "2.7" +install: + - mkdir -p buildout-cache/eggs + - mkdir -p buildout-cache/downloads + - python bootstrap.py -c travis.cfg + - bin/buildout -N -t 3 -c travis.cfg +script: bin/test diff --git a/buildout.cfg b/buildout.cfg index 1f8d641..40f065d 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,8 +1,9 @@ [buildout] parts = instance + test -extends = http://dist.plone.org/release/4.2.2/versions.cfg +extends = http://dist.plone.org/release/4.2.1/versions.cfg versions = versions develop = . @@ -11,7 +12,7 @@ extensions = mr.developer sources = sources auto-checkout = * -sources-dir = src-mrd +sources-dir = src eggs = zcml = @@ -30,6 +31,11 @@ environment-vars = zcml = ${buildout:zcml} +[test] +recipe = zc.recipe.testrunner +eggs = pcommerce.core [test] +defaults = ['--auto-color', '--auto-progress'] + [sources] [versions] diff --git a/setup.py b/setup.py index e692c5e..1ffdea7 100644 --- a/setup.py +++ b/setup.py @@ -30,6 +30,12 @@ 'Products.SingleKeywordWidget', # -*- Extra requirements: -*- ], + extras_require = { + 'test': [ + 'plone.app.testing', + 'Products.SingleKeywordWidget', + ] + }, entry_points=""" # -*- Entry points: -*- [z3c.autoinclude.plugin] diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py new file mode 100644 index 0000000..00fb1a0 --- /dev/null +++ b/src/pcommerce/core/testing.py @@ -0,0 +1,40 @@ +from plone.testing import z2 + +from plone.app.testing import PloneSandboxLayer +from plone.app.testing import PLONE_FIXTURE +from plone.app.testing import IntegrationTesting +from plone.app.testing import applyProfile +from plone.app.testing import quickInstallProduct +from plone.app.testing import ploneSite + +class pcommerceCoreTddLayer(PloneSandboxLayer): + + defaultBases = (PLONE_FIXTURE,) + + def setUpZope(self, app, configurationContext): + # Load ZCML + import pcommerce.core + import Products.SingleKeywordWidget + self.loadZCML(package=pcommerce.core) + self.loadZCML(package=Products.SingleKeywordWidget) + + # Install product and call its initialize() function + z2.installProduct(app, 'pcommerce.core') + + # Note: you can skip this if my.product is not a Zope 2-style + # product, i.e. it is not in the Products.* namespace and it + # does not have a directive in its + # configure.zcml. + + def setUpPloneSite(self, portal): + # Install into Plone site using portal_setup + quickInstallProduct(portal, 'pcommerce.core') + + def tearDownZope(self, app): + # Uninstall product + z2.uninstallProduct(app, 'pcommerce.core') + +PCOMMERCE_TDD_FIXTURE = pcommerceCoreTddLayer() +PCOMMERCE_TDD_INTEGRATION_TESTING = IntegrationTesting( + bases=(PCOMMERCE_TDD_FIXTURE,), + name="pcommerceTddLayer:Integration") diff --git a/src/pcommerce/core/tests/__init__.py b/src/pcommerce/core/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pcommerce/core/tests/test_integration.py b/src/pcommerce/core/tests/test_integration.py new file mode 100644 index 0000000..f8a85b3 --- /dev/null +++ b/src/pcommerce/core/tests/test_integration.py @@ -0,0 +1,24 @@ +import unittest2 as unittest + +from plone.app.testing import PloneSandboxLayer +from plone.app.testing import PLONE_FIXTURE +from plone.app.testing import IntegrationTesting +from plone.app.testing import applyProfile +from plone.app.testing import quickInstallProduct +from plone.app.testing import ploneSite +from plone.app.testing import setRoles +from plone.app.testing import TEST_USER_ID + +from Products.CMFCore.utils import getToolByName + +from pcommerce.core.testing import PCOMMERCE_TDD_INTEGRATION_TESTING + +class PcommerceTest(unittest.TestCase): + + layer = PCOMMERCE_TDD_INTEGRATION_TESTING + + def test_pcommerce_content_type_installed(self): + portal = self.layer['portal'] + typesTool = getToolByName(portal, 'portal_types') + self.assertNotEqual(typesTool.getTypeInfo('Product'), None) + diff --git a/travis.cfg b/travis.cfg new file mode 100644 index 0000000..cbbed81 --- /dev/null +++ b/travis.cfg @@ -0,0 +1,17 @@ +[buildout] +extends = buildout.cfg +parts = + download + install + test +eggs-directory = buildout-cache/eggs +download-cache = buildout-cache/downloads + +[download] +recipe = hexagonit.recipe.download +url = https://launchpad.net/plone/4.2/4.2.1/+download/Plone-4.2.1-UnifiedInstaller.tgz + +[install] +recipe = collective.recipe.cmd +on_install = true +cmds = tar jxvf ${download:location}/Plone-4.2.1-UnifiedInstaller/packages/buildout-cache.tar.bz2 1>/dev/null From 8dbc18bb6a858b5a4ed3d99fd007d6f18b8d2efa Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 14:21:58 +0100 Subject: [PATCH 05/27] added other test --- src/pcommerce/core/tests/test_integration.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pcommerce/core/tests/test_integration.py b/src/pcommerce/core/tests/test_integration.py index f8a85b3..fcad468 100644 --- a/src/pcommerce/core/tests/test_integration.py +++ b/src/pcommerce/core/tests/test_integration.py @@ -22,3 +22,11 @@ def test_pcommerce_content_type_installed(self): typesTool = getToolByName(portal, 'portal_types') self.assertNotEqual(typesTool.getTypeInfo('Product'), None) + def test_content_creation(self): + portal = self.layer['portal'] + setRoles(portal, TEST_USER_ID, ['Manager']) + portal.invokeFactory('Product', 'TestProduct') + product = portal['TestProduct'] + self.assertEqual(product.getTitle(), u"TestProduct") + + From afcb25630d99db91c1f3dc4c459bb38c11ef4b48 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 14:48:47 +0100 Subject: [PATCH 06/27] better travis conf --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6d194c7..28f0b09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,10 @@ language: python python: "2.7" +branches: + only: + - noreg_order +notifications: + irc: "irc.freenode.org#starzel" install: - mkdir -p buildout-cache/eggs - mkdir -p buildout-cache/downloads From 266343fb4e50d6e1d9f8fd547e0f4219eca96e54 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 15:40:31 +0100 Subject: [PATCH 07/27] Content test, TravisImage --- README.rst | 3 +++ buildout.cfg | 4 ++++ setup.py | 2 ++ src/pcommerce/core/testing.py | 8 ++++++++ src/pcommerce/core/tests/test_integration.py | 4 ++-- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 5c13a36..234c24a 100644 --- a/README.rst +++ b/README.rst @@ -3,6 +3,9 @@ Introduction PCommerce (Plone commerce) provides a simple shop system which supports: +.. image:: https://api.travis-ci.org/Gomez/pcommerce.core.png + :target: http://travis-ci.org/Gomez/pcommerce.core.png + * product variations * multiple prices per product to support special prices per user or group (over the sharing tab) and prices only available for a specific time diff --git a/buildout.cfg b/buildout.cfg index 40f065d..7489d78 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -25,6 +25,8 @@ eggs = Plone Pillow pcommerce.core + pcommerce.shipment.parcel + pcommerce.payment.invoice environment-vars = zope_i18n_compile_mo_files true @@ -39,3 +41,5 @@ defaults = ['--auto-color', '--auto-progress'] [sources] [versions] +pcommerce.payment.invoice = 1.0b5 +pcommerce.shipment.parcel = 1.0b2 diff --git a/setup.py b/setup.py index 1ffdea7..32d1c7f 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,8 @@ 'test': [ 'plone.app.testing', 'Products.SingleKeywordWidget', + 'pcommerce.shipment.parcel', + 'pcommerce.payment.invoice', ] }, entry_points=""" diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py index 00fb1a0..4363612 100644 --- a/src/pcommerce/core/testing.py +++ b/src/pcommerce/core/testing.py @@ -15,11 +15,15 @@ def setUpZope(self, app, configurationContext): # Load ZCML import pcommerce.core import Products.SingleKeywordWidget + import pcommerce.shipment.parcel + import pcommerce.payment.invoice self.loadZCML(package=pcommerce.core) self.loadZCML(package=Products.SingleKeywordWidget) # Install product and call its initialize() function z2.installProduct(app, 'pcommerce.core') + z2.installProduct(app, 'pcommerce.shipment.parcel') + z2.installProduct(app, 'pcommerce.shipment.invoice') # Note: you can skip this if my.product is not a Zope 2-style # product, i.e. it is not in the Products.* namespace and it @@ -29,10 +33,14 @@ def setUpZope(self, app, configurationContext): def setUpPloneSite(self, portal): # Install into Plone site using portal_setup quickInstallProduct(portal, 'pcommerce.core') + quickInstallProduct(portal, 'pcommerce.shipment.parcel') + quickInstallProduct(portal, 'pcommerce.shipment.invoice') def tearDownZope(self, app): # Uninstall product z2.uninstallProduct(app, 'pcommerce.core') + z2.uninstallProduct(app, 'pcommerce.shipment.parcel') + z2.uninstallProduct(app, 'pcommerce.shipment.invoice') PCOMMERCE_TDD_FIXTURE = pcommerceCoreTddLayer() PCOMMERCE_TDD_INTEGRATION_TESTING = IntegrationTesting( diff --git a/src/pcommerce/core/tests/test_integration.py b/src/pcommerce/core/tests/test_integration.py index fcad468..c77ab54 100644 --- a/src/pcommerce/core/tests/test_integration.py +++ b/src/pcommerce/core/tests/test_integration.py @@ -25,8 +25,8 @@ def test_pcommerce_content_type_installed(self): def test_content_creation(self): portal = self.layer['portal'] setRoles(portal, TEST_USER_ID, ['Manager']) - portal.invokeFactory('Product', 'TestProduct') + portal.invokeFactory('Product', 'TestProduct', shipments='pcommerce.shipment.parcel',title='TestProduct') product = portal['TestProduct'] - self.assertEqual(product.getTitle(), u"TestProduct") + self.assertEqual(product.Title(), u"TestProduct") From b0b1d80f9fd2c328013b55149c7e059c7e7ec03c Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 17:50:23 +0100 Subject: [PATCH 08/27] Functional test layer added --- src/pcommerce/core/testing.py | 3 +++ src/pcommerce/core/tests/test_integration.py | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py index 4363612..b08f98a 100644 --- a/src/pcommerce/core/testing.py +++ b/src/pcommerce/core/testing.py @@ -3,6 +3,7 @@ from plone.app.testing import PloneSandboxLayer from plone.app.testing import PLONE_FIXTURE from plone.app.testing import IntegrationTesting +from plone.app.testing import FunctionalTesting from plone.app.testing import applyProfile from plone.app.testing import quickInstallProduct from plone.app.testing import ploneSite @@ -43,6 +44,8 @@ def tearDownZope(self, app): z2.uninstallProduct(app, 'pcommerce.shipment.invoice') PCOMMERCE_TDD_FIXTURE = pcommerceCoreTddLayer() +PCOMMERCE_FUNCTIONAL_TESTING = FunctionalTesting(bases=(PCOMMERCE_TDD_FIXTURE,), name="pcommerceTddLayer::Functional") + PCOMMERCE_TDD_INTEGRATION_TESTING = IntegrationTesting( bases=(PCOMMERCE_TDD_FIXTURE,), name="pcommerceTddLayer:Integration") diff --git a/src/pcommerce/core/tests/test_integration.py b/src/pcommerce/core/tests/test_integration.py index c77ab54..3e7222e 100644 --- a/src/pcommerce/core/tests/test_integration.py +++ b/src/pcommerce/core/tests/test_integration.py @@ -1,5 +1,7 @@ import unittest2 as unittest +from zope.component import getUtility + from plone.app.testing import PloneSandboxLayer from plone.app.testing import PLONE_FIXTURE from plone.app.testing import IntegrationTesting @@ -8,6 +10,9 @@ from plone.app.testing import ploneSite from plone.app.testing import setRoles from plone.app.testing import TEST_USER_ID +from plone.app.testing import SITE_OWNER_NAME, SITE_OWNER_PASSWORD + +from plone.testing.z2 import Browser from Products.CMFCore.utils import getToolByName @@ -29,4 +34,3 @@ def test_content_creation(self): product = portal['TestProduct'] self.assertEqual(product.Title(), u"TestProduct") - From ff67703d534b0ca46f6c60e4a064178c57acf11f Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 19:06:10 +0100 Subject: [PATCH 09/27] Now with robotframework --- .travis.yml | 3 +++ setup.py | 2 ++ src/pcommerce/core/testing.py | 27 ++++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 28f0b09..7bc4acb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,7 @@ install: - mkdir -p buildout-cache/downloads - python bootstrap.py -c travis.cfg - bin/buildout -N -t 3 -c travis.cfg +before_script: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" script: bin/test diff --git a/setup.py b/setup.py index 32d1c7f..d065103 100644 --- a/setup.py +++ b/setup.py @@ -36,6 +36,8 @@ 'Products.SingleKeywordWidget', 'pcommerce.shipment.parcel', 'pcommerce.payment.invoice', + 'robotsuite', + 'robotframework-selenium2library', ] }, entry_points=""" diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py index b08f98a..d14443e 100644 --- a/src/pcommerce/core/testing.py +++ b/src/pcommerce/core/testing.py @@ -1,3 +1,9 @@ +from plone.testing.z2 import ZSERVER_FIXTURE + +import transaction +from Testing import ZopeTestCase as ztc +from OFS.Folder import Folder + from plone.testing import z2 from plone.app.testing import PloneSandboxLayer @@ -12,6 +18,11 @@ class pcommerceCoreTddLayer(PloneSandboxLayer): defaultBases = (PLONE_FIXTURE,) + #We create our own Session + class Session(dict): + def set(self, key, value): + self[key] = value + def setUpZope(self, app, configurationContext): # Load ZCML import pcommerce.core @@ -31,6 +42,16 @@ def setUpZope(self, app, configurationContext): # does not have a directive in its # configure.zcml. + # ------------------------------------------------------------------------- + # support for sessions without invalidreferences if using zeo temp storage + # ------------------------------------------------------------------------- + app.REQUEST['SESSION'] = self.Session() + if not hasattr(app, 'temp_folder'): + tf = Folder('temp_folder') + app._setObject('temp_folder', tf) + transaction.commit() + ztc.utils.setupCoreSessions(app) + def setUpPloneSite(self, portal): # Install into Plone site using portal_setup quickInstallProduct(portal, 'pcommerce.core') @@ -43,9 +64,13 @@ def tearDownZope(self, app): z2.uninstallProduct(app, 'pcommerce.shipment.parcel') z2.uninstallProduct(app, 'pcommerce.shipment.invoice') + PCOMMERCE_TDD_FIXTURE = pcommerceCoreTddLayer() -PCOMMERCE_FUNCTIONAL_TESTING = FunctionalTesting(bases=(PCOMMERCE_TDD_FIXTURE,), name="pcommerceTddLayer::Functional") PCOMMERCE_TDD_INTEGRATION_TESTING = IntegrationTesting( bases=(PCOMMERCE_TDD_FIXTURE,), name="pcommerceTddLayer:Integration") + +PCOMMERCE_TDD_ACCEPTANCE_TESTING = FunctionalTesting( + bases=(PCOMMERCE_TDD_FIXTURE, ZSERVER_FIXTURE), + name="pcommerceTddLayer:Acceptance") From 13ca160a7c8015577d1f754d105574fa1072425f Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Fri, 11 Jan 2013 19:12:49 +0100 Subject: [PATCH 10/27] With Acceptance tests --- src/pcommerce/core/tests/acceptance/login.txt | 39 +++++++++++++++++++ src/pcommerce/core/tests/test_acceptance.py | 21 ++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/pcommerce/core/tests/acceptance/login.txt create mode 100644 src/pcommerce/core/tests/test_acceptance.py diff --git a/src/pcommerce/core/tests/acceptance/login.txt b/src/pcommerce/core/tests/acceptance/login.txt new file mode 100644 index 0000000..42a7401 --- /dev/null +++ b/src/pcommerce/core/tests/acceptance/login.txt @@ -0,0 +1,39 @@ +*** Settings *** + +Library Selenium2Library run_on_failure=Capture Page Screenshot +Variables plone/app/testing/interfaces.py + +Suite Setup Start browser +Suite Teardown Close All Browsers + +*** Variables *** + +${PORT} = 55001 +${ZOPE_URL} = http://localhost:${PORT} +${PLONE_URL} = ${ZOPE_URL}/plone + + +*** Test cases *** + +Test Valid Login + Set Selenium Speed 0.5 seconds + Given a login form + When I enter valid credentials + Then I am logged in + + +*** Keywords *** + +Start browser + Open browser http://localhost:55001/plone/ + +a login form + Go to ${PLONE_URL}/login_form + +I enter valid credentials + Input text __ac_name ${TEST_USER_NAME} + Input text __ac_password ${TEST_USER_PASSWORD} + Click Button Log in + +I am logged in + Page should contain logged in diff --git a/src/pcommerce/core/tests/test_acceptance.py b/src/pcommerce/core/tests/test_acceptance.py new file mode 100644 index 0000000..fb7ada5 --- /dev/null +++ b/src/pcommerce/core/tests/test_acceptance.py @@ -0,0 +1,21 @@ +import os +import unittest + +from plone.testing import layered + +import robotsuite + +from pcommerce.core.testing import PCOMMERCE_TDD_ACCEPTANCE_TESTING + +def test_suite(): + suite = unittest.TestSuite() + current_dir = os.path.abspath(os.path.dirname(__file__)) + acceptance_dir = os.path.join(current_dir, 'acceptance') + acceptance_tests = [os.path.join('acceptance', doc) for doc in + os.listdir(acceptance_dir) if doc.endswith('.txt')] + for test in acceptance_tests: + suite.addTests([ + layered(robotsuite.RobotTestSuite(test), + layer=PCOMMERCE_TDD_ACCEPTANCE_TESTING), + ]) + return suite From 26b218c4a301a6dccd1311479886e2903e500cc2 Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Sat, 12 Jan 2013 13:56:23 +0100 Subject: [PATCH 11/27] Registration needed tests --- buildout.cfg | 8 +++ setup.py | 1 + src/pcommerce/core/testing.py | 2 + src/pcommerce/core/tests/acceptance/login.txt | 39 -------------- .../tests/acceptance/test_pcommerce_core.txt | 52 +++++++++++++++++++ 5 files changed, 63 insertions(+), 39 deletions(-) delete mode 100644 src/pcommerce/core/tests/acceptance/login.txt create mode 100644 src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt diff --git a/buildout.cfg b/buildout.cfg index 7489d78..33a2573 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -1,5 +1,6 @@ [buildout] parts = + lxml instance test @@ -24,6 +25,7 @@ eggs = ${buildout:eggs} Plone Pillow + plone.act pcommerce.core pcommerce.shipment.parcel pcommerce.payment.invoice @@ -33,13 +35,19 @@ environment-vars = zcml = ${buildout:zcml} +[lxml] +recipe = z3c.recipe.staticlxml +egg = lxml + [test] recipe = zc.recipe.testrunner eggs = pcommerce.core [test] defaults = ['--auto-color', '--auto-progress'] [sources] +plone.act = git git://github.com/plone/plone.act.git [versions] pcommerce.payment.invoice = 1.0b5 pcommerce.shipment.parcel = 1.0b2 +lxml = 2.2.4 diff --git a/setup.py b/setup.py index d065103..f31099c 100644 --- a/setup.py +++ b/setup.py @@ -33,6 +33,7 @@ extras_require = { 'test': [ 'plone.app.testing', + 'plone.act', 'Products.SingleKeywordWidget', 'pcommerce.shipment.parcel', 'pcommerce.payment.invoice', diff --git a/src/pcommerce/core/testing.py b/src/pcommerce/core/testing.py index d14443e..1581080 100644 --- a/src/pcommerce/core/testing.py +++ b/src/pcommerce/core/testing.py @@ -30,6 +30,8 @@ def setUpZope(self, app, configurationContext): import pcommerce.shipment.parcel import pcommerce.payment.invoice self.loadZCML(package=pcommerce.core) + self.loadZCML(package=pcommerce.shipment.parcel) + self.loadZCML(package=pcommerce.payment.invoice) self.loadZCML(package=Products.SingleKeywordWidget) # Install product and call its initialize() function diff --git a/src/pcommerce/core/tests/acceptance/login.txt b/src/pcommerce/core/tests/acceptance/login.txt deleted file mode 100644 index 42a7401..0000000 --- a/src/pcommerce/core/tests/acceptance/login.txt +++ /dev/null @@ -1,39 +0,0 @@ -*** Settings *** - -Library Selenium2Library run_on_failure=Capture Page Screenshot -Variables plone/app/testing/interfaces.py - -Suite Setup Start browser -Suite Teardown Close All Browsers - -*** Variables *** - -${PORT} = 55001 -${ZOPE_URL} = http://localhost:${PORT} -${PLONE_URL} = ${ZOPE_URL}/plone - - -*** Test cases *** - -Test Valid Login - Set Selenium Speed 0.5 seconds - Given a login form - When I enter valid credentials - Then I am logged in - - -*** Keywords *** - -Start browser - Open browser http://localhost:55001/plone/ - -a login form - Go to ${PLONE_URL}/login_form - -I enter valid credentials - Input text __ac_name ${TEST_USER_NAME} - Input text __ac_password ${TEST_USER_PASSWORD} - Click Button Log in - -I am logged in - Page should contain logged in diff --git a/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt new file mode 100644 index 0000000..6262ad7 --- /dev/null +++ b/src/pcommerce/core/tests/acceptance/test_pcommerce_core.txt @@ -0,0 +1,52 @@ +*** Settings *** + +Library Selenium2Library run_on_failure=Capture Page Screenshot +Variables plone/app/testing/interfaces.py + +Resource plone/act/keywords.txt + +Suite Setup Start browser +Suite Teardown Close All Browsers + +*** Variables *** + +${front-page} http://localhost:55001/plone/ +${test-folder} http://localhost:55001/plone/pcommerce-test-folder +${control-panel} http://localhost:55001/plone/@@overview-controlpanel + +${PORT} = 55001 +${ZOPE_URL} = http://localhost:${PORT} +${PLONE_URL} = ${ZOPE_URL}/plone + +*** Keywords *** + +Start browser + Open browser ${front-page} + +Create Product + [Arguments] ${title} + Go to ${front-page}/createObject?type_name=Product + Input text title ${title} + Click Button Save + +*** Test Cases *** + +Test Noregistration switch visible + Log in as site owner + Go to ${front-page}/@@pcommerce_configlet + + Element Should Be Visible id=noregistration_order + + +Test Registration needed + Log in as site owner + Create Product My product + Page should contain Changes saved. + #Workflow Publish + Log out + Go to ${front-page}/my-product + Click Button add to cart + Page should contain Added item to cart + Go to ${front-page}/@@cart + + Page should contain You have to be registered to check out your order, From a4f70e69ce442740613d8f53c276682a76c5b40f Mon Sep 17 00:00:00 2001 From: Steffen Lindner Date: Sat, 12 Jan 2013 16:01:41 +0100 Subject: [PATCH 12/27] First step for no registration with tests --- src/pcommerce/core/browser/cart.py | 8 +++-- src/pcommerce/core/browser/configlet.pt | 6 ++-- src/pcommerce/core/browser/configlet.py | 34 ++++++++++--------- .../tests/acceptance/test_pcommerce_core.txt | 34 +++++++++++++++++-- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/pcommerce/core/browser/cart.py b/src/pcommerce/core/browser/cart.py index 39fdd9b..4235783 100644 --- a/src/pcommerce/core/browser/cart.py +++ b/src/pcommerce/core/browser/cart.py @@ -33,7 +33,11 @@ def products(self): @property @memoize def checkout(self): - return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) + noregistration = getToolByName(self.context, 'portal_properties').pcommerce_properties.noregistration_order + if noregistration: + return True + else: + return getToolByName(self.context, 'portal_membership').checkPermission(CheckOut, self.context) @property @memoize @@ -46,4 +50,4 @@ def taxincl(self): taxes = ITaxes(self.context) return {'tax': taxes.taxincl[0], 'taxname': taxes.taxincl[1]} - \ No newline at end of file + diff --git a/src/pcommerce/core/browser/configlet.pt b/src/pcommerce/core/browser/configlet.pt index e171474..7dd96e3 100644 --- a/src/pcommerce/core/browser/configlet.pt +++ b/src/pcommerce/core/browser/configlet.pt @@ -139,7 +139,7 @@
    -
    @@ -193,11 +193,9 @@
  • - The Error -