예제 #1
0
class OrderLineTax(MoneyPropped, ShoopModel, LineTax):
    order_line = models.ForeignKey(OrderLine,
                                   related_name='taxes',
                                   on_delete=models.PROTECT,
                                   verbose_name=_('order line'))
    tax = models.ForeignKey("Tax",
                            related_name="order_line_taxes",
                            on_delete=models.PROTECT,
                            verbose_name=_('tax'))
    name = models.CharField(max_length=200, verbose_name=_('tax name'))

    amount = MoneyProperty('amount_value', 'order_line.order.currency')
    base_amount = MoneyProperty('base_amount_value',
                                'order_line.order.currency')

    amount_value = MoneyValueField(verbose_name=_('tax amount'))
    base_amount_value = MoneyValueField(
        verbose_name=_('base amount'),
        help_text=_('Amount that this tax is calculated from'))

    ordering = models.IntegerField(default=0, verbose_name=_('ordering'))

    class Meta:
        ordering = ["ordering"]

    def __str__(self):
        return "%s: %s on %s" % (self.name, self.amount, self.base_amount)
예제 #2
0
파일: _payments.py 프로젝트: teserak/shoop
class Payment(MoneyPropped, models.Model):
    # TODO: Revise!!!
    order = models.ForeignKey("Order", related_name='payments', on_delete=models.PROTECT, verbose_name=_('order'))
    created_on = models.DateTimeField(auto_now_add=True, verbose_name=_('created on'))
    gateway_id = models.CharField(max_length=32, verbose_name=_('gateway ID'))  # TODO: do we need this?
    payment_identifier = models.CharField(max_length=96, unique=True, verbose_name=_('identifier'))

    amount = MoneyProperty('amount_value', 'order.currency')
    foreign_amount = MoneyProperty('foreign_amount_value', 'foreign_currency')

    amount_value = MoneyValueField(verbose_name=_('amount'))
    foreign_amount_value = MoneyValueField(default=None, blank=True, null=True, verbose_name=_('foreign amount'))
    foreign_currency = CurrencyField(default=None, blank=True, null=True, verbose_name=_('foreign amount currency'))

    description = models.CharField(max_length=256, blank=True, verbose_name=_('description'))

    class Meta:
        verbose_name = _('payment')
        verbose_name_plural = _('payments')
예제 #3
0
class Tax(MoneyPropped, ImmutableMixin, TranslatableShoopModel):
    identifier_attr = 'code'

    immutability_message = _(
        "Cannot change business critical fields of Tax that is in use")
    unprotected_fields = ['enabled']

    code = InternalIdentifierField(unique=True,
                                   editable=True,
                                   verbose_name=_("code"),
                                   help_text="")

    translations = TranslatedFields(name=models.CharField(
        max_length=64, verbose_name=_("name")), )

    rate = models.DecimalField(max_digits=6,
                               decimal_places=5,
                               blank=True,
                               null=True,
                               verbose_name=_("tax rate"),
                               help_text=_("The percentage rate of the tax."))
    amount = MoneyProperty('amount_value', 'currency')
    amount_value = MoneyValueField(
        default=None,
        blank=True,
        null=True,
        verbose_name=_("tax amount value"),
        help_text=_("The flat amount of the tax. "
                    "Mutually exclusive with percentage rates."))
    currency = CurrencyField(default=None,
                             blank=True,
                             null=True,
                             verbose_name=_("currency of tax amount"))

    enabled = models.BooleanField(default=True, verbose_name=_('enabled'))

    def clean(self):
        super(Tax, self).clean()
        if self.rate is None and self.amount is None:
            raise ValidationError(_('Either rate or amount is required'))
        if self.amount is not None and self.rate is not None:
            raise ValidationError(_('Cannot have both rate and amount'))
        if self.amount is not None and not self.currency:
            raise ValidationError(
                _("Currency is required if amount is specified"))

    def calculate_amount(self, base_amount):
        """
        Calculate tax amount with this tax for given base amount.

        :type base_amount: shoop.utils.money.Money
        :rtype: shoop.utils.money.Money
        """
        if self.amount is not None:
            return self.amount
        if self.rate is not None:
            return self.rate * base_amount
        raise ValueError("Improperly configured tax: %s" % self)

    def __str__(self):
        text = super(Tax, self).__str__()
        if self.rate is not None:
            text += " ({})".format(format_percent(self.rate, digits=3))
        if self.amount is not None:
            text += " ({})".format(format_money(self.amount))
        return text

    def _is_in_use(self):
        return self.order_line_taxes.exists()

    class Meta:
        verbose_name = _('tax')
        verbose_name_plural = _('taxes')
예제 #4
0
    class Wallet(object):
        amount = MoneyProperty('value', 'currency')

        def __init__(self):
            self.value = 42
            self.currency = 'EUR'