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…
	
	Add table
		Add a link
		
	
		Reference in a new issue