forked from uncloud/uncloud
Merge branch 'master' of code.ungleich.ch:uncloud/uncloud
This commit is contained in:
commit
b55254b9b1
1 changed files with 74 additions and 1 deletions
|
@ -41,10 +41,10 @@ class RecurringPeriod(models.TextChoices):
|
||||||
ONE_TIME = 'ONCE', _('Onetime')
|
ONE_TIME = 'ONCE', _('Onetime')
|
||||||
PER_YEAR = 'YEAR', _('Per Year')
|
PER_YEAR = 'YEAR', _('Per Year')
|
||||||
PER_MONTH = 'MONTH', _('Per Month')
|
PER_MONTH = 'MONTH', _('Per Month')
|
||||||
PER_MINUTE = 'MINUTE', _('Per Minute')
|
|
||||||
PER_WEEK = 'WEEK', _('Per Week')
|
PER_WEEK = 'WEEK', _('Per Week')
|
||||||
PER_DAY = 'DAY', _('Per Day')
|
PER_DAY = 'DAY', _('Per Day')
|
||||||
PER_HOUR = 'HOUR', _('Per Hour')
|
PER_HOUR = 'HOUR', _('Per Hour')
|
||||||
|
PER_MINUTE = 'MINUTE', _('Per Minute')
|
||||||
PER_SECOND = 'SECOND', _('Per Second')
|
PER_SECOND = 'SECOND', _('Per Second')
|
||||||
|
|
||||||
|
|
||||||
|
@ -540,6 +540,10 @@ class Product(UncloudModel):
|
||||||
editable=False,
|
editable=False,
|
||||||
null=True)
|
null=True)
|
||||||
|
|
||||||
|
# Default period for all products
|
||||||
|
default_recurring_period = RecurringPeriod.PER_MONTH
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
|
def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
|
||||||
pass # To be implemented in child.
|
pass # To be implemented in child.
|
||||||
|
@ -558,3 +562,72 @@ class Product(UncloudModel):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
def discounted_price_by_period(self, requested_period):
|
||||||
|
"""
|
||||||
|
Each product has a standard recurring period for which
|
||||||
|
we define a pricing. I.e. VPN is usually year, VM is usually monthly.
|
||||||
|
|
||||||
|
The user can opt-in to use a different period, which influences the price:
|
||||||
|
The longer a user commits, the higher the discount.
|
||||||
|
|
||||||
|
Products can also be limited in the available periods. For instance
|
||||||
|
a VPN only makes sense to be bought for at least one day.
|
||||||
|
|
||||||
|
Rules are as follows:
|
||||||
|
|
||||||
|
given a standard recurring period of ..., changing to ... modifies price ...
|
||||||
|
|
||||||
|
|
||||||
|
# One month for free if buying / year, compared to a month: about 8.33% discount
|
||||||
|
per_year -> per_month -> /11
|
||||||
|
per_month -> per_year -> *11
|
||||||
|
|
||||||
|
# Month has 30.42 days on average. About 7.9% discount to go monthly
|
||||||
|
per_month -> per_day -> /28
|
||||||
|
per_day -> per_month -> *28
|
||||||
|
|
||||||
|
# Day has 24h, give one for free
|
||||||
|
per_day -> per_hour -> /23
|
||||||
|
per_hour -> per_day -> /23
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
|
||||||
|
VPN @ 120CHF/y becomes
|
||||||
|
- 10.91 CHF/month (130.91 CHF/year)
|
||||||
|
- 0.39 CHF/day (142.21 CHF/year)
|
||||||
|
|
||||||
|
VM @ 15 CHF/month becomes
|
||||||
|
- 165 CHF/month (13.75 CHF/month)
|
||||||
|
- 0.54 CHF/day (16.30 CHF/month)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
if self.default_recurring_period == RecurringPeriod.PER_YEAR:
|
||||||
|
if requested_period == RecurringPeriod.PER_YEAR:
|
||||||
|
return self.recurring_price
|
||||||
|
if requested_period == RecurringPeriod.PER_MONTH:
|
||||||
|
return self.recurring_price/11.
|
||||||
|
if requested_period == RecurringPeriod.PER_DAY:
|
||||||
|
return self.recurring_price/11./28.
|
||||||
|
|
||||||
|
elif self.default_recurring_period == RecurringPeriod.PER_MONTH:
|
||||||
|
if requested_period == RecurringPeriod.PER_YEAR:
|
||||||
|
return self.recurring_price*11
|
||||||
|
if requested_period == RecurringPeriod.PER_MONTH:
|
||||||
|
return self.recurring_price
|
||||||
|
if requested_period == RecurringPeriod.PER_DAY:
|
||||||
|
return self.recurring_price/28.
|
||||||
|
|
||||||
|
elif self.default_recurring_period == RecurringPeriod.PER_DAY:
|
||||||
|
if requested_period == RecurringPeriod.PER_YEAR:
|
||||||
|
return self.recurring_price*11*28
|
||||||
|
if requested_period == RecurringPeriod.PER_MONTH:
|
||||||
|
return self.recurring_price*28
|
||||||
|
if requested_period == RecurringPeriod.PER_DAY:
|
||||||
|
return self.recurring_price
|
||||||
|
else:
|
||||||
|
# FIXME: use the right type of exception here!
|
||||||
|
raise Exception("Did not implement the discounter for this case")
|
||||||
|
|
Loading…
Reference in a new issue