add a discounter function to the product model
This commit is contained in:
parent
9431f11284
commit
05f38d157e
1 changed files with 74 additions and 1 deletions
|
@ -28,9 +28,9 @@ class RecurringPeriod(models.TextChoices):
|
|||
ONE_TIME = 'ONCE', _('Onetime')
|
||||
PER_YEAR = 'YEAR', _('Per Year')
|
||||
PER_MONTH = 'MONTH', _('Per Month')
|
||||
PER_MINUTE = 'MINUTE', _('Per Minute')
|
||||
PER_DAY = 'DAY', _('Per Day')
|
||||
PER_HOUR = 'HOUR', _('Per Hour')
|
||||
PER_MINUTE = 'MINUTE', _('Per Minute')
|
||||
PER_SECOND = 'SECOND', _('Per Second')
|
||||
|
||||
|
||||
|
@ -456,6 +456,10 @@ class Product(UncloudModel):
|
|||
editable=False,
|
||||
null=True)
|
||||
|
||||
# Default period for all products
|
||||
default_recurring_period = RecurringPeriod.PER_MONTH
|
||||
|
||||
|
||||
@property
|
||||
def recurring_price(self, recurring_period=RecurringPeriod.PER_MONTH):
|
||||
pass # To be implemented in child.
|
||||
|
@ -474,3 +478,72 @@ class Product(UncloudModel):
|
|||
|
||||
class Meta:
|
||||
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