Пример #1
0
    def add_extra_cart_row(self, cart, request):
        """
        Add a field on cart.extra_price_fields:
        """
        subtotal10 = (cart.items.filter(product__tax_switch=False).values(
            'quantity',
            'product__unit_price').aggregate(total=ExpressionWrapper(
                Sum(F('quantity') * F('product__unit_price')), DecimalField()))
                      )['total']  # 10 percent tax
        subtotal20 = (cart.items.filter(product__tax_switch=True).values(
            'quantity',
            'product__unit_price').aggregate(total=ExpressionWrapper(
                Sum(F('quantity') * F('product__unit_price')), DecimalField()))
                      )['total']  # 20 percent tax

        amount10 = (subtotal10 or 0) * self.taxes10
        amount20 = (subtotal20 or 0) * self.taxes20

        instance10 = {
            'label':
            _("{}% VAT incl.").format(settings.SHOP_VALUE_ADDED_TAX10),
            'amount': Money(amount10),
        }
        instance20 = {
            'label': _("{}% VAT incl.").format(settings.SHOP_VALUE_ADDED_TAX),
            'amount': Money(amount20),
        }
        cart.extra_rows[self.identifier + '10'] = ExtraCartRow(instance10)
        cart.extra_rows[self.identifier + '20'] = ExtraCartRow(instance20)
Пример #2
0
    def create_products(self):
        manufacturer = Manufacturer.objects.create(name="SanDisk")
        sdhc_4gb = SmartCard.objects.create(
            product_name="SDHC Card 4GB",
            slug="sdhc-card-4gb",
            unit_price=Money('3.99'),
            caption="Dependability and solid performance",
            manufacturer=manufacturer,
            card_type="SDHC",
            storage=4,
            speed=4,
            product_code="sd1041",
            description="SanDisk SDHC and SDXC memory cards are great",
            order=1)
        ProductPage.objects.create(page=self.shop_page, product=sdhc_4gb)
        ProductPage.objects.create(page=self.smartcards_page, product=sdhc_4gb)

        xtr_sdhc_16gb = SmartCard.objects.create(
            product_name="EXTREME PLUS SDHC 16GB",
            slug="extreme-plus-sdhc-16gb",
            unit_price=Money('8.49'),
            caption="Up to 80/60MB/s read/write speed",
            manufacturer=manufacturer,
            card_type="SDHC",
            storage=16,
            speed=80,
            product_code="sd2016",
            description=
            "SanDisk Extreme memory cards offer speed, capacity, and durability",
            order=2,
        )
        ProductPage.objects.create(page=self.shop_page, product=xtr_sdhc_16gb)
        ProductPage.objects.create(page=self.smartcards_page,
                                   product=xtr_sdhc_16gb)
Пример #3
0
 def get_default_caption_data(cls):
     return {
         'num_items': 0,
         'total_quantity': 0,
         'subtotal': Money(),
         'total': Money()
     }
Пример #4
0
def get_price_steps(steps=5, products=None):
    """
    Returns min and max price with the steps in between.

    {% get_price_steps 3 products as price_steps %}
    """
    queryset = Product.objects.active().top_level()

    if products is not None:
        queryset = queryset.filter(id__in=[x.id for x in products])
    if not queryset:
        return []

    queryset = queryset.order_by('_unit_price')
    min_price, max_price = math.floor(queryset.first().unit_price), math.ceil(
        queryset.last().unit_price)
    if max_price == min_price:
        return [Money(min_price)]

    price_steps = [Money(min_price)]
    chunk = Money(int(max_price - min_price) / (steps + 1))
    for i in range(steps):
        price_steps.append(price_steps[-1] + chunk)
    price_steps = sorted(list(set(price_steps)))
    price_steps.append(Money(max_price))

    return price_steps
Пример #5
0
 def get_default_caption_data(cls):
     warnings.warn("This method is deprecated")
     return {
         'num_items': 0,
         'total_quantity': 0,
         'subtotal': Money(),
         'total': Money()
     }
Пример #6
0
 def add_extra_cart_row(self, cart, request):
     shipping_modifiers = cart_modifiers_pool.get_shipping_modifiers()
     if not self.is_active(cart.extra.get(
             'shipping_modifier')) and len(shipping_modifiers) > 1:
         return
     # add a shipping flat fee
     amount = Money('5')
     if cart.total >= Money(100):
         amount = Money('0')
     instance = {'label': _("Shipping costs"), 'amount': amount}
     cart.extra_rows[self.identifier] = ExtraCartRow(instance)
     cart.total += amount
Пример #7
0
 def add_extra_cart_row(self, cart, request):
     if not self.is_active(cart.extra.get('payment_modifier')) and len(cart_modifiers_pool.get_payment_modifiers()) > 1:
         return False
     amount = Money('30')
     instance = {'label': _("Extra charge by post"), 'amount': amount}
     cart.extra_rows[self.identifier] = ExtraCartRow(instance)
     cart.total += amount
Пример #8
0
 def add_extra_cart_row(self, cart, request):
     if not self.is_active(cart.extra.get('shipping_modifier')) and len(
             cart_modifiers_pool.get_shipping_modifiers()) > 1:
         return
     amount = Money(settings.WELTLADEN_BIKING_PRICE)
     instance = {'label': _("Shipping costs"), 'amount': amount}
     cart.extra_rows[self.identifier] = ExtraCartRow(instance)
     cart.total += amount
Пример #9
0
 def create_modifier(self, name, amount=0, percent=None, **kwargs):
     attrs = {
         'name': name,
         'code': slugify(name),
         'amount': Money(amount),
         'percent': D(percent) if percent else None
     }
     attrs.update(kwargs)
     return Modifier.objects.language().create(**attrs)
Пример #10
0
 def add_extra_cart_row(self, cart, request):
     for modifier in Modifier.get_cart_modifiers():
         if modifier.can_be_applied(request, cart=cart):
             amount = modifier.get_added_amount(cart.total)
             instance = {'label': modifier.label, 'amount': amount, 'code': self.get_applied_code(modifier)}
             cart.extra_rows[modifier.code] = ExtraCartRow(instance)
             cart.total += amount
             if cart.total < 0:
                 cart.total = Money(0)
Пример #11
0
 def add_extra_cart_item_row(self, cart_item, request):
     for modifier in cart_item.product.get_modifiers():
         if modifier.can_be_applied(request, cart_item=cart_item):
             amount = modifier.get_added_amount(cart_item.line_total, cart_item.quantity)
             instance = {'label': modifier.label, 'amount': amount, 'code': self.get_applied_code(modifier)}
             cart_item.extra_rows[modifier.code] = ExtraCartRow(instance)
             cart_item.line_total += amount
             if cart_item.line_total < 0:
                 cart_item.line_total = Money(0)
Пример #12
0
 def add_extra_cart_row(self, cart, request):
     if not self.is_active(cart) and len(
             cart_modifiers_pool.get_shipping_modifiers()) > 1:
         return
     # add a shipping flat fee
     amount = Money('3')
     instance = {'label': _("Courier shipping costs"), 'amount': amount}
     cart.extra_rows[self.identifier] = ExtraCartRow(instance)
     cart.total += amount
Пример #13
0
class CartIconCaptionSerializer(serializers.ModelSerializer):
    """
    The default serializer used to render the information nearby the cart icon symbol, normally
    located on the top right of e-commerce sites.
    """
    num_items = serializers.IntegerField(read_only=True, default=0)
    total = MoneyField(default=Money())

    class Meta:
        model = CartModel
        fields = ['num_items', 'total']
Пример #14
0
def empty_cart(rf, api_client):
    request = rf.get('/my-cart')
    request.session = api_client.session
    request.user = AnonymousUser()
    request.customer = Customer.objects.get_or_create_from_request(request)
    request.customer.email = '*****@*****.**'
    request.customer.save()
    cart = CartModel.objects.get_from_request(request)
    cart.update(request)
    assert cart.is_empty
    assert cart.subtotal == Money(0)
    return cart
Пример #15
0
 def get_price(self, request):
     """
     Return the starting price for instances of this smart phone model.
     """
     if not hasattr(self, '_price'):
         if self.variants.exists():
             currency = self.variants.first().unit_price.currency
             aggr = self.variants.aggregate(models.Min('unit_price'))
             self._price = MoneyMaker(currency)(aggr['unit_price__min'])
         else:
             self._price = Money()
     return self._price
Пример #16
0
 def create_product(self,
                    name,
                    kind=Product.SINGLE,
                    unit_price=0,
                    **kwargs):
     attrs = {
         'name': name,
         'slug': slugify(name),
         'code': slugify(name),
         'kind': kind,
         'unit_price': Money(unit_price)
     }
     attrs.update(kwargs)
     return Product.objects.language().create(**attrs)
Пример #17
0
class CommodityFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Commodity

    product_name = factory.fuzzy.FuzzyText(prefix='Product-')
    product_code = factory.Sequence(lambda n: 'article-{}'.format(n + 1))
    unit_price = Money(factory.fuzzy.FuzzyDecimal(1, 100).fuzz())
    slug = factory.fuzzy.FuzzyText(length=7)

    @classmethod
    def create(cls, **kwargs):
        product = super(CommodityFactory, cls).create(**kwargs)
        page = create_page("Catalog", 'page.html', 'en')
        ProductPageModel.objects.create(page=page, product=product)
        return product
Пример #18
0
    def add_extra_cart_row(self, cart, request):
        if not self.is_active(cart.extra.get('shipping_modifier')) and len(cart_modifiers_pool.get_shipping_modifiers()) > 1:
            return
        # add a shipping flat fee
        amount = Money('5')
        if cart.total_weight<1:
            amount = Money('4')
        elif cart.total_weight >=1 and cart.total_weight < 3:
            amount = Money('7.5')
        elif cart.total_weight >=3 and cart.total_weight < 15:
            amount = Money('10')
        elif cart.total_weight >=15 and cart.total_weight < 30:
            amount = Money('20')
        elif cart.total_weight > 30:
            amount = Money('500')
        else:
            amount = Money('999')

        instance = {'label': _("Shipping costs"), 'amount': amount}
        cart.extra_rows[self.identifier] = ExtraCartRow(instance)
        cart.total += amount
Пример #19
0
    def setUp(self):
        self.create_request()

        self.mod1 = self.create_modifier('Mod1', percent=-10)
        self.cond1 = self.create_modifier_condition(
            self.mod1,
            'shopit.modifier_conditions.QuantityGreaterThanCondition',
            2)  # noqa
        self.cond2 = self.create_modifier_condition(
            self.mod1, 'shopit.modifier_conditions.PriceGreaterThanCondition',
            10)  # noqa
        self.p1 = self.create_product('P1', unit_price=20)

        CartItem.objects.get_or_create(cart=self.cart,
                                       product=self.p1,
                                       quantity=1)
        self.cart_items = CartItem.objects.filter_cart_items(
            self.cart, self.request)

        self.cart.total = Money(
            sum([
                x.product.get_price(self.request) * x.quantity
                for x in self.cart_items
            ]))
Пример #20
0
 def add_extra_cart_row(self, cart, request):
     if not self.is_active(cart) and len(
             cart_modifiers_pool.get_shipping_modifiers()) > 1:
         return
     # postal tarifs by Siarhei
     if cart.total_weight < 1:
         amount = Money('6')
     elif cart.total_weight >= 1 and cart.total_weight < 3:
         amount = Money('9')
     elif cart.total_weight >= 3 and cart.total_weight < 15:
         amount = Money('12')
     elif cart.total_weight >= 15 and cart.total_weight < 30:
         amount = Money('23')
     elif cart.total_weight > 30:
         amount = Money('500')
     else:
         amount = Money('999')
     # add a shipping flat fee
     instance = {'label': _("Shipping costs to home"), 'amount': amount}
     cart.extra_rows[self.identifier] = ExtraCartRow(instance)
     cart.total += amount
Пример #21
0
 def test_get_price(self):
     p = self.create_product('P', unit_price=300)
     self.assertEquals(self.admin.get_price(p), str(Money(300)))
Пример #22
0
 def get_price(self, request):
     aggregate = self.variants.aggregate(models.Min('unit_price'))
     return Money(aggregate['unit_price__min'])
 def test_get_value(self):
     m1 = self.create_modifier('M1', amount=-10)
     m2 = self.create_modifier('M2', percent=-10)
     self.assertEquals(self.admin.get_value(m1), str(Money(-10)))
     self.assertEquals(self.admin.get_value(m2),
                       '{} %'.format(Decimal(-10)))
Пример #24
0
class Modifier(TranslatableModel):
    STANDARD = 'standard'
    DISCOUNT = 'discount'
    CART = 'cart'

    KINDS = (
        (STANDARD, _('Standard')),
        (DISCOUNT, _('Discount')),
        (CART, _('Cart')),
    )

    translations = TranslatedFields(name=models.CharField(_('Name'),
                                                          max_length=128), )

    code = models.SlugField(
        _('Code'),
        unique=True,
        help_text=_('Unique identifier for this modifier.'))

    amount = MoneyField(
        _('Amount'),
        default=Money(0),
        help_text=('Amount that should be added. Can be negative.'))

    percent = models.DecimalField(
        _('Percent'),
        blank=True,
        null=True,
        max_digits=4,
        decimal_places=2,
        help_text=
        _('Percent that should be added, overrides the amount. Can be negative.'
          ))

    kind = models.CharField(
        _('Kind'),
        max_length=16,
        choices=KINDS,
        default=STANDARD,
        help_text=_(
            'Standard affects the product regardles, Discount checks for a "Discountable" flag on a product and should be '
            'negative, Cart will affect an entire cart.'))

    active = models.BooleanField(
        _('Active'),
        default=True,
        help_text=_('Is this modifier publicly visible.'))
    created_at = models.DateTimeField(_('Created at'), auto_now_add=True)
    updated_at = models.DateTimeField(_('Updated at'), auto_now=True)
    order = models.PositiveIntegerField(_('Sort'), default=0)

    objects = ModifierQuerySet.as_manager()

    class Meta:
        db_table = 'shopit_modifiers'
        verbose_name = _('Modifier')
        verbose_name_plural = _('Modifiers')
        ordering = ['order']

    def __str__(self):
        return self.label

    def save(self, *args, **kwargs):
        self.clean()
        super(Modifier, self).save(*args, **kwargs)

    @property
    def label(self):
        return self.safe_translation_getter('name', any_language=True)

    @property
    def requires_code(self):
        return self.discount_codes.active().exists()

    @property
    def is_filtering_enabled(self):
        return Modifier.objects.filtering_enabled().active().filter(
            id=self.id).exists()

    def get_conditions(self):
        if not hasattr(self, '_conditions'):
            setattr(self, '_conditions', list(self.conditions.all()))
        return getattr(self, '_conditions')

    def get_discount_codes(self, include_added=False):
        key = '_discount_codes_added' if include_added else '_discount_codes'
        if not hasattr(self, key):
            setattr(
                self, key,
                list(self.discount_codes.valid(include_added=include_added)))
        return getattr(self, key)

    def get_added_amount(self, price, quantity=1):
        return self.percent * price / 100 if self.percent else self.amount * quantity

    def can_be_applied(self, request, cart_item=None, cart=None):
        """
        Returns if a modifier can be applied to the given cart or cart item.
        Either `cart_item` or `cart` must be passed in.
        """
        if cart_item is None and cart is None:
            return False

        if cart_item and not self.is_eligible_product(cart_item.product):
            return False

        for condition in self.get_conditions():
            if not condition.is_met(request, cart_item, cart):
                return False

        if self.requires_code and not self.is_code_applied(
                cart_item.cart_id if cart_item else cart.id):
            return False

        return self.active  # Should never happen to be False up to this point, but just in case.

    def is_eligible_product(self, product):
        """
        Returns if modifier can be applied to the given product.
        """
        if self.kind == self.DISCOUNT:
            return product.discountable
        return self.kind == self.STANDARD

    def is_code_applied(self, cart_id):
        """
        Make sure that at least one code is applied to the given cart.
        """
        cart_codes = CartDiscountCode.objects.filter(
            cart_id=cart_id).values_list('code', flat=True)
        for code in self.get_discount_codes(include_added=True):
            if code.code in cart_codes:
                return True
        return False

    def clean(self):
        if self.kind == self.DISCOUNT:
            if self.percent and self.percent >= 0 or not self.percent and self.amount >= 0:
                raise ValidationError(EM['discount_not_negative'])

    @classmethod
    def get_cart_modifiers(cls):
        return cls.objects.filter(kind=cls.CART)
 def cart_item_condition(self, request, cart_item, value=0):
     return cart_item.line_total < Money(value)
Пример #26
0
 def process_cart(self, cart, request):
     if not isinstance(cart.subtotal, AbstractMoney):
         # if we don't know the currency, use the default
         cart.subtotal = Money(cart.subtotal)
     cart.total = cart.subtotal
     return super().process_cart(cart, request)
 def cart_condition(self, request, cart, value=0):
     return cart.total < Money(value)