Ejemplo n.º 1
0
    def contextualize_or_complete(self, request, context, data=None):

        completed = True
        customer = self.customer
        user = customer.user
        user_form = None

        if user.pk is None:
            # No prefixing here, in order to utilize overlapping fields
            user_form = UserCreationForm(data, instance=user)

            completed &= data and user_form.is_valid()
            if completed:
                user = user_form.save(commit=False)
            context['user_form'] = user_form

        # No prefixing here, in order to utilize overlapping fields
        customer_form = CustomerForm(data, instance=customer)

        completed &= data and customer_form.is_valid()
        if completed:
            customer = customer_form.save(commit=False)
        context['customer_form'] = customer_form

        # We are overlapping customer form fields with user form fields.
        # This will most likely only be the 'email' field. Since additional
        # validation happens by the user form, we need to copy over
        # these errors to the customer form.
        if user_form is not None:
            for field, error in six.iteritems(user_form.errors.as_data()):
                if field in customer_form.fields:
                    customer_form.add_error(field, error)

        addresses = {}
        for address_type in ADDRESS_TYPES:
            form = AddressForm(
                data,
                prefix=underscore_concat(address_type, 'address'),
                instance=customer.addresses.get(address_type, None),
            )

            completed &= data and form.is_valid()
            if completed:
                address = form.save(commit=False)
                addresses[address_type] = address
            context[underscore_concat(address_type, 'address_form')] = form

        if completed:
            for address_type in ADDRESS_TYPES:
                address = addresses[address_type]
                customer.addresses[address_type] = address

            customer.user = user

        return completed
Ejemplo n.º 2
0
    def contextualize_or_complete(self, request, context, data=None):

        completed = True
        order = self.order

        # Contact information
        form = ContactableForm(data, prefix='contactable', instance=order)

        completed &= data and form.is_valid()
        if completed:
            order = form.save(commit=False)
        context['contactable_form'] = form

        # Shipping method
        shipping_method = None
        if order.needs_shipping():
            initial = {}
            if order.shipping_method is not None:
                initial['method'] = order.shipping_method.string
            form = ShippingMethodForm.factory(get_shippings_methods(
                self.order))(
                    data,
                    prefix='shipping_method',
                    initial=initial
                )

            completed &= data and form.is_valid()
            if completed:
                shipping_method = form.cleaned_data['shipping_method']
            context['shipping_method_form'] = form

        # Addresses
        addresses = {}
        for address_type in ADDRESS_TYPES:
            form = AddressForm(
                data,
                prefix=underscore_concat(address_type, 'address'),
                instance=order.addresses.get(address_type, None)
            )

            completed &= data and form.is_valid()
            if completed:
                address = form.save(commit=False)
                addresses[address_type] = address

            context[underscore_concat(address_type, 'address_form')] = form

        if completed:
            order.invalidate()
            order.shipping_method = shipping_method
            for address_type in ADDRESS_TYPES:
                address = addresses[address_type]
                order.addresses[address_type] = address

        return completed
Ejemplo n.º 3
0
    def contextualize_or_complete(self, request, context, data=None):

        completed = True
        customer = self.customer
        user = customer.user
        user_form = None

        if user.pk is None:
            # No prefixing here, in order to utilize overlapping fields
            user_form = UserCreationForm(data, instance=user)

            completed &= data and user_form.is_valid()
            if completed:
                user = user_form.save(commit=False)
            context['user_form'] = user_form

        # No prefixing here, in order to utilize overlapping fields
        customer_form = CustomerForm(data, instance=customer)

        completed &= data and customer_form.is_valid()
        if completed:
            customer = customer_form.save(commit=False)
        context['customer_form'] = customer_form

        # We are overlapping customer form fields with user form fields.
        # This will most likely only be the 'email' field. Since additional
        # validation happens by the user form, we need to copy over
        # these errors to the customer form.
        if user_form is not None:
            for field, error in six.iteritems(user_form.errors.as_data()):
                if field in customer_form.fields:
                    customer_form.add_error(field, error)

        addresses = {}
        for address_type in ADDRESS_TYPES:
            form = AddressForm(
                data,
                prefix=underscore_concat(address_type, 'address'),
                instance=customer.addresses.get(address_type, None),
            )

            completed &= data and form.is_valid()
            if completed:
                address = form.save(commit=False)
                addresses[address_type] = address
            context[underscore_concat(address_type, 'address_form')] = form

        if completed:
            for address_type in ADDRESS_TYPES:
                address = addresses[address_type]
                customer.addresses[address_type] = address

            customer.user = user

        return completed
Ejemplo n.º 4
0
def price_field_names(
    name,
    multi_currency=False,
    currencies=True,
    components=None,
    extra_fields=False,
    components_only=False
):

    result = []
    currencies = resolve_currencies(currencies)
    components = resolve_components(components)
    if multi_currency:
        for currency in currencies:
            if not components_only:
                result.append(price_field_name(name, currency=currency))
            for component in components:
                for multiplicity in range(1, component.multiplicity + 1):
                    field_name = price_field_name(
                        name,
                        currency=currency,
                        component=component,
                        multiplicity=multiplicity
                    )
                    result.append(field_name)
                    if extra_fields:
                        for extra_field_name in component.extra_fields:
                            full_extra_field_name = underscore_concat(
                                field_name, extra_field_name
                            )
                            result.append(full_extra_field_name)
    else:
        if not components_only:
            result.append(price_field_name(name))
            result.append(currency_field_name(name))
        for component in components:
            for multiplicity in range(1, component.multiplicity + 1):
                field_name = price_field_name(
                    name,
                    component=component,
                    multiplicity=multiplicity
                )
                result.append(field_name)
                if extra_fields:
                    for extra_field_name in component.extra_fields:
                        full_extra_field_name = underscore_concat(
                            field_name, extra_field_name
                        )
                        result.append(full_extra_field_name)

    return result
Ejemplo n.º 5
0
    def get_fields(self):
        fields = super(PriceIndex, self).get_fields()

        for prefix in self.price_prefixes:
            for currency in Currency.get_all():

                field_name = price_field_name(prefix, currency=currency)
                fields[field_name] = indexing.DecimalField(
                    max_digits=DECIMAL_MAX_DIGITS,
                    decimal_places=DECIMAL_PLACES
                )

                for component in Price.COMPONENTS:
                    field_names = price_field_names(
                        prefix,
                        multi_currency=True,
                        currencies=[currency],
                        components=[component],
                        components_only=True
                    )
                    for field_name in field_names:
                        fields[field_name] = indexing.DecimalField(
                            max_digits=DECIMAL_MAX_DIGITS,
                            decimal_places=DECIMAL_PLACES
                        )

                        for extra_field_name, extra_field in six.iteritems(
                            component.construct_extra_index_fields()
                        ):
                            full_extra_field_name = underscore_concat(
                                field_name, extra_field_name
                            )
                            fields[full_extra_field_name] = extra_field

        return fields
Ejemplo n.º 6
0
    def get_fields(self):
        fields = super(PriceIndex, self).get_fields()

        for prefix in self.price_prefixes:
            for currency in Currency.get_all():

                field_name = price_field_name(prefix, currency=currency)
                fields[field_name] = indexing.DecimalField(
                    max_digits=DECIMAL_MAX_DIGITS,
                    decimal_places=DECIMAL_PLACES)

                for component in Price.COMPONENTS:
                    field_names = price_field_names(prefix,
                                                    multi_currency=True,
                                                    currencies=[currency],
                                                    components=[component],
                                                    components_only=True)
                    for field_name in field_names:
                        fields[field_name] = indexing.DecimalField(
                            max_digits=DECIMAL_MAX_DIGITS,
                            decimal_places=DECIMAL_PLACES)

                        for extra_field_name, extra_field in six.iteritems(
                                component.construct_extra_index_fields()):
                            full_extra_field_name = underscore_concat(
                                field_name, extra_field_name)
                            fields[full_extra_field_name] = extra_field

        return fields
Ejemplo n.º 7
0
def price_field_name(name, currency=None, component=None, multiplicity=None):
    parts = [name]
    if currency is not None:
        parts.append(currency)
    if component is not None:
        if multiplicity is not None and multiplicity > 1:
            component = '%s%s' % (component, multiplicity)
        parts.append(component)
    else:
        parts.append(AMOUNT_FIELD)

    return underscore_concat(*parts)
Ejemplo n.º 8
0
    def get_indexed_price(self, document, prefix, currency=None):
        values = getattr(document, '_index_values', {})
        field_name = price_field_name(prefix, currency=currency)

        if field_name not in values:
            raise Exception("%s not found in index" % field_name)

        amount = values.get(field_name)

        if amount is None:
            return None

        price = Price(amount, currency=currency)

        for component in Price.COMPONENTS:
            field_names = price_field_names(
                prefix,
                multi_currency=True,
                currencies=[currency],
                components=[component],
                components_only=True
            )
            for field_name in field_names:
                if field_name not in values:
                    raise Exception("%s not found in index" % field_name)
                amount = values[field_name]
                if amount is None:
                    # Due to multiplicity, we can have unused fields.
                    # Do not apply these.
                    continue
                extra_values = {}

                for extra_field_name in component.extra_fields:
                    full_extra_field_name = underscore_concat(
                        field_name, extra_field_name
                    )
                    if full_extra_field_name not in values:
                        raise Exception(
                            "%s not found in index" % full_extra_field_name
                        )
                    extra_values[
                        extra_field_name
                    ] = values[full_extra_field_name]

                amount, extra_values = component.prepare_from_index(
                    amount, extra_values
                )
                price = component.apply(price, amount, extra_values)

        return price
Ejemplo n.º 9
0
    def populate(self, document, values, **variety):
        values = super(PriceIndex, self).populate(document, values, **variety)
        kwargs = self.get_price_kwargs(document, **variety)

        for prefix in self.price_prefixes:
            for currency in Currency.get_all():
                try:
                    price = self.get_price(
                        document, prefix, currency, **kwargs
                    )
                except CurrencyNotAvailable:
                    price = None

                if price is None:
                    continue

                field_name = price_field_name(prefix, currency=currency)
                values[field_name] = price.amount

                for component in Price.COMPONENTS:
                    multiplicity = 0
                    for (
                        amount, extra_values
                    ) in component.safe_extract(price):
                        multiplicity += 1

                        field_name = price_field_name(
                            prefix,
                            currency=currency,
                            component=component,
                            multiplicity=multiplicity
                        )
                        amount, extra_values = component.prepare_for_index(
                            amount, extra_values
                        )

                        values[field_name] = amount
                        for extra_field_name in component.extra_fields:
                            full_extra_field_name = underscore_concat(
                                field_name, extra_field_name
                            )
                            values[full_extra_field_name] = extra_values.get(
                                extra_field_name
                            )

        return values
Ejemplo n.º 10
0
    def get_indexed_price(self, document, prefix, currency=None):
        values = getattr(document, '_index_values', {})
        field_name = price_field_name(prefix, currency=currency)

        if field_name not in values:
            raise Exception("%s not found in index" % field_name)

        amount = values.get(field_name)

        if amount is None:
            return None

        price = Price(amount, currency=currency)

        for component in Price.COMPONENTS:
            field_names = price_field_names(prefix,
                                            multi_currency=True,
                                            currencies=[currency],
                                            components=[component],
                                            components_only=True)
            for field_name in field_names:
                if field_name not in values:
                    raise Exception("%s not found in index" % field_name)
                amount = values[field_name]
                if amount is None:
                    # Due to multiplicity, we can have unused fields.
                    # Do not apply these.
                    continue
                extra_values = {}

                for extra_field_name in component.extra_fields:
                    full_extra_field_name = underscore_concat(
                        field_name, extra_field_name)
                    if full_extra_field_name not in values:
                        raise Exception("%s not found in index" %
                                        full_extra_field_name)
                    extra_values[extra_field_name] = values[
                        full_extra_field_name]

                amount, extra_values = component.prepare_from_index(
                    amount, extra_values)
                price = component.apply(price, amount, extra_values)

        return price
Ejemplo n.º 11
0
    def contruct_component_field(self, name, component, currency=None):
        fields = {}

        if self.multi_currency:
            field_names = price_field_names(
                name,
                multi_currency=self.multi_currency,
                currencies=[currency],
                components=[component],
                components_only=True
            )
        else:
            field_names = price_field_names(
                name,
                components=[component],
                components_only=True
            )

        for field_name in field_names:
            fargs = {'null': True, 'blank': True}

            verbose_name = []
            if self.verbose_name is not None:
                verbose_name.append(self.verbose_name)
            verbose_name.extend([" ", component.verbose_name])

            if currency is not None:
                verbose_name.extend([" (", currency.name, ")"])

            fargs['verbose_name'] = string_concat(*verbose_name)

            for extra_field_name, extra_field in six.iteritems(
                component.construct_extra_model_fields()
            ):
                full_extra_field_name = underscore_concat(
                    field_name, extra_field_name
                )
                fields[full_extra_field_name] = extra_field

            fields[field_name] = StandardizedDecimalField(**fargs)
        return fields
Ejemplo n.º 12
0
    def populate(self, document, values, **variety):
        values = super(PriceIndex, self).populate(document, values, **variety)
        kwargs = self.get_price_kwargs(document, **variety)

        for prefix in self.price_prefixes:
            for currency in Currency.get_all():
                try:
                    price = self.get_price(document, prefix, currency,
                                           **kwargs)
                except CurrencyNotAvailable:
                    price = None

                if price is None:
                    continue

                field_name = price_field_name(prefix, currency=currency)
                values[field_name] = price.amount

                for component in Price.COMPONENTS:
                    multiplicity = 0
                    for (amount,
                         extra_values) in component.safe_extract(price):
                        multiplicity += 1

                        field_name = price_field_name(
                            prefix,
                            currency=currency,
                            component=component,
                            multiplicity=multiplicity)
                        amount, extra_values = component.prepare_for_index(
                            amount, extra_values)

                        values[field_name] = amount
                        for extra_field_name in component.extra_fields:
                            full_extra_field_name = underscore_concat(
                                field_name, extra_field_name)
                            values[full_extra_field_name] = extra_values.get(
                                extra_field_name)

        return values
Ejemplo n.º 13
0
def differs_field_name(field_name):
    return underscore_concat(field_name, 'differs')
Ejemplo n.º 14
0
# specific prior written permission.

# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from sellmo.apps.customer.constants import ADDRESS_TYPES
from sellmo.utils.text import underscore_concat

from .price import TaxPriceComponent

TAX = TaxPriceComponent()

POLICY_CUSTOMER_ADDRESS = 'address'
POLICY_CUSTOMER_ADDRESS_TYPES = {
    underscore_concat(POLICY_CUSTOMER_ADDRESS, address_type): address_type
    for address_type in ADDRESS_TYPES
}

DISPLAY_PRICES_INCLUDING_TAX = 'including_tax'
DISPLAY_PRICES_EXCLUDING_TAX = 'excluding_tax'
DISPLAY_PRICES_INCLUDING_EXCLUDING_TAX = 'including_excluding_tax'
Ejemplo n.º 15
0
from sellmo.apps.customer.constants import ADDRESS_TYPES
from sellmo.utils.text import underscore_concat

from sellmo.contrib.settings import settings_manager
from sellmo.contrib.settings.signals import setting_changed

from .models import Tax, TaxRule, ProductTaxClass
from .constants import (TAX, DISPLAY_PRICES_INCLUDING_TAX,
                        DISPLAY_PRICES_EXCLUDING_TAX,
                        DISPLAY_PRICES_INCLUDING_EXCLUDING_TAX,
                        POLICY_CUSTOMER_ADDRESS)

group = _("Taxes")

POLICY_CHOICES = tuple(
    (underscore_concat(POLICY_CUSTOMER_ADDRESS, address_type),
     _("%s address") % address_type) for address_type in ADDRESS_TYPES)

POLICY_DEFAULT = POLICY_CHOICES[0][0] if POLICY_CHOICES else None

settings_manager.add_setting(
    'tax_policy',
    models.CharField(
        max_length=80,
        null=POLICY_DEFAULT is None,
        blank=POLICY_DEFAULT is None,
        default=POLICY_DEFAULT,
        choices=POLICY_CHOICES,
        verbose_name=_("tax policy"),
    ), group)
Ejemplo n.º 16
0
def setting_key(key, prefix=None):
    if prefix:
        key = underscore_concat(prefix, key)
    return key
Ejemplo n.º 17
0
 def __hash__(self):
     return hash(
         underscore_concat('attr', self.value.attribute.key, 'value',
                           self.value.value))
Ejemplo n.º 18
0
 def cache_tag_key(self, tag):
     return self.cache_key(underscore_concat(TAG_PREFIX, tag))
Ejemplo n.º 19
0
 def cache_key(self, key):
     return underscore_concat(self.prefix, key)
Ejemplo n.º 20
0
def differs_field_name(field_name):
    return underscore_concat(field_name, 'differs')
Ejemplo n.º 21
0
 def __hash__(self):
     return hash(
         underscore_concat(
             'attr', self.value.attribute.key, 'value', self.value.value
         )
     )
Ejemplo n.º 22
0
def currency_field_name(name):
    return underscore_concat(name, CURRENCY_FIELD)