Source code for plans.plan_change

# coding=utf-8
from decimal import Decimal

[docs]class PlanChangePolicy(object): def _calculate_day_cost(self, plan, period): """ Finds most fitted plan pricing for a given period, and calculate day cost """ plan_pricings = plan.planpricing_set.order_by('-pricing__period').select_related('pricing') selected_pricing = None for plan_pricing in plan_pricings: selected_pricing = plan_pricing if plan_pricing.pricing.period <= period: break if selected_pricing: return (selected_pricing.price / selected_pricing.pricing.period).quantize(Decimal('1.00')) raise ValueError('Plan %s has no pricings.' % plan) def _calculate_final_price(self, period, day_cost_diff): if day_cost_diff is None: return None else: return period * day_cost_diff
[docs] def get_change_price(self, plan_old, plan_new, period): """ Calculates total price of plan change. Returns None if no payment is required. """ if period is None or period < 1: return None plan_old_day_cost = self._calculate_day_cost(plan_old, period) plan_new_day_cost = self._calculate_day_cost(plan_new, period) if plan_new_day_cost <= plan_old_day_cost: return self._calculate_final_price(period, None) else: return self._calculate_final_price(period, plan_new_day_cost - plan_old_day_cost)
[docs]class StandardPlanChangePolicy(PlanChangePolicy): """ This plan switch policy follows the rules: * user can downgrade a plan for free if the plan is cheaper or have exact the same price (additional constant charge can be applied) * user need to pay extra amount depending of plans price difference (additional constant charge can be applied) Change percent rate while upgrading is defined in ``StandardPlanChangePolicy.UPGRADE_PERCENT_RATE`` Additional constant charges are: * ``StandardPlanChangePolicy.UPGRADE_CHARGE`` * ``StandardPlanChangePolicy.FREE_UPGRADE`` * ``StandardPlanChangePolicy.DOWNGRADE_CHARGE`` .. note:: Example User has PlanA which costs monthly (30 days) 20 €. His account will expire in 23 days. He wants to change to PlanB which costs monthly (30 days) 50€. Calculations:: PlanA costs per day 20 €/ 30 days = 0.67 € PlanB costs per day 50 €/ 30 days = 1.67 € Difference per day between PlanA and PlanB is 1.00 € Upgrade percent rate is 10% Constant upgrade charge is 0 € Switch cost is: 23 * 1.00 € * 10% + 0 € = 25.30 € days_left * cost_diff_per_day * upgrade_percent_rate + constant_upgrade_charge """ UPGRADE_PERCENT_RATE = Decimal('10.0') UPGRADE_CHARGE = Decimal('0.0') DOWNGRADE_CHARGE = None FREE_UPGRADE = Decimal('0.0') def _calculate_final_price(self, period, day_cost_diff): if day_cost_diff is None: return self.DOWNGRADE_CHARGE cost = (period * day_cost_diff * (self.UPGRADE_PERCENT_RATE/100 + 1) + self.UPGRADE_CHARGE).quantize(Decimal('1.00')) if cost is None or cost < self.FREE_UPGRADE: return None else: return cost