def __init__(self, order): self._order = order self._price_resolver = PriceResolver() self.charging_processors = { 'initial': self._process_initial_charge, 'recurring': self._process_renovation_charge, 'usage': self._process_use_charge } self.end_processors = { 'initial': self._end_initial_charge, 'recurring': self._end_renovation_charge, 'usage': self._end_use_charge }
def resolve_charging(self, new_purchase=False, sdr=False): # Check if there is a new purchase if new_purchase: # Create the contract self._create_purchase_contract() charge = False related_model = {} # Check if there are price parts different from pay per use if 'single_payment' in self._price_model: charge = True related_model['single_payment'] = self._price_model[ 'single_payment'] if 'subscription' in self._price_model: charge = True related_model['subscription'] = self._price_model[ 'subscription'] price = 0 if charge: # Call the price resolver resolver = PriceResolver() price = resolver.resolve_price(related_model) # Check user expenditure limits and accumulated balance self._check_expenditure_limits(price) # Make the charge redirect_url = self._charge_client( price, 'initial charge', self._price_model['general_currency']) else: # If it is not necessary to charge the customer the state is set to paid self._purchase.state = 'paid' if self._purchase.state == 'paid': self.end_charging(price, 'initial charge', related_model) else: price = self._fix_price(price) self._purchase.contract.pending_payment = { 'price': price, 'concept': 'initial charge', 'related_model': related_model } self._purchase.contract.save() return redirect_url else: self._price_model = self._purchase.contract.pricing_model self._purchase.state = 'pending' self._purchase.save() # If not SDR received means that the call is a renovation if not sdr: # Determine the price parts to renovate if 'subscription' not in self._price_model: raise Exception('No subscriptions to renovate') related_model = {'subscription': []} now = datetime.now() unmodified = [] for s in self._price_model['subscription']: renovation_date = s['renovation_date'] if renovation_date < now: related_model['subscription'].append(s) else: unmodified.append(s) accounting_info = None # If pending SDR documents resolve the use charging if len(self._purchase.contract.pending_sdrs) > 0: related_model['pay_per_use'] = self._price_model[ 'pay_per_use'] accounting_info = [] accounting_info.extend( self._purchase.contract.pending_sdrs) # If deductions have been included resolve the discount if 'deductions' in self._price_model and len( self._price_model['deductions']) > 0: related_model['deductions'] = self._price_model[ 'deductions'] resolver = PriceResolver() price = resolver.resolve_price(related_model, accounting_info) # Deductions can make the price 0 if price > 0: # If not use made, check expenditure limits and accumulated balance if not accounting_info: self._check_expenditure_limits(price) redirect_url = self._charge_client( price, 'Renovation', self._price_model['general_currency']) if len(unmodified) > 0: related_model['unmodified'] = unmodified # Check if applied accounting info is needed to finish the purchase applied_accounting = None if accounting_info: applied_accounting = resolver.get_applied_sdr() if self._purchase.state == 'paid': self.end_charging(price, 'Renovation', related_model, applied_accounting) else: price = self._fix_price(price) pending_payment = { 'price': price, 'concept': 'Renovation', 'related_model': related_model } # If some accounting has been used include it to be saved if accounting_info: pending_payment['accounting'] = applied_accounting self._purchase.contract.pending_payment self._purchase.contract.save() return redirect_url # If sdr is true means that the call is a request for charging the use # made of a service. else: # Aggregate the calculated charges pending_sdrs = [] pending_sdrs.extend(self._purchase.contract.pending_sdrs) if len(pending_sdrs) == 0: raise Exception('No SDRs to charge') related_model = { 'pay_per_use': self._price_model['pay_per_use'] } if 'deductions' in self._price_model and len( self._price_model['deductions']) > 0: related_model['deductions'] = self._price_model[ 'deductions'] resolver = PriceResolver() price = resolver.resolve_price(related_model, pending_sdrs) # Charge the client # Deductions can make the price 0 if price > 0: redirect_url = self._charge_client( price, 'Pay per use', self._price_model['general_currency']) applied_accounting = resolver.get_applied_sdr() if self._purchase.state == 'paid': self.end_charging(price, 'pay per use', related_model, applied_accounting) else: price = self._fix_price(price) self._purchase.contract.pending_payment = { 'price': price, 'concept': 'pay per use', 'related_model': related_model, 'accounting': applied_accounting } self._purchase.contract.save() return redirect_url