def create(self, request): try: event = json.loads(request.body) except: return build_response( request, 400, 'The provided data is not a valid JSON object') if event['eventType'] != 'ProductCreationNotification': return build_response(request, 200, 'OK') product = event['event']['product'] # Extract order id order_id = product['name'].split('=')[1] # Get order order = Order.objects.get(order_id=order_id) contract = None # Search contract for cont in order.contracts: if product['productOffering']['id'] == cont.offering.off_id: contract = cont if contract is None: return build_response( request, 404, 'There is not a contract for the specified product') # Save contract id contract.product_id = product['id'] order.save() # Activate asset try: on_product_acquired(order, contract) except: return build_response(request, 400, 'The asset has failed to be activated') # Change product state to active inventory_client = InventoryClient() inventory_client.activate_product(product['id']) # Create the initial charge in the billing API if len(contract.charges) == 1: billing_client = BillingClient() valid_to = None # If the initial charge was a subscription is needed to determine the expiration date if 'subscription' in contract.pricing_model: valid_to = contract.pricing_model['subscription'][0][ 'renovation_date'] billing_client.create_charge(contract.charges[0], contract.product_id, start_date=None, end_date=valid_to) return build_response(request, 200, 'OK')
def end_charging(self, transactions, free_contracts, concept): """ Process the second step of a payment once the customer has approved the charge :param transactions: List of transactions applied including the total price and the related model :param concept: Concept of the charge, it can be initial, renovation, or use """ # Update purchase state if self._order.state == 'pending': self._order.state = 'paid' self._order.save() time_stamp = datetime.utcnow() self._order.pending_payment = {} invoice_builder = InvoiceBuilder(self._order) billing_client = BillingClient() if concept != 'initial' else None for transaction in transactions: contract = self._order.get_item_contract(transaction['item']) contract.last_charge = time_stamp valid_from, valid_to = self.end_processors[concept](contract, transaction) # If the customer has been charged create the CDR cdr_manager = CDRManager(self._order, contract) cdr_manager.generate_cdr(transaction['related_model'], time_stamp.isoformat() + 'Z') # Generate the invoice invoice_path = '' try: invoice_path = invoice_builder.generate_invoice(contract, transaction, concept) except: pass # Update contracts charge = Charge( date=time_stamp, cost=transaction['price'], duty_free=transaction['duty_free'], currency=transaction['currency'], concept=concept, invoice=invoice_path ) contract.charges.append(charge) # Send the charge to the billing API to allow user accesses if concept != 'initial': # When the change concept is initial, the product has not been yet created in the inventory billing_client.create_charge(charge, contract.product_id, start_date=valid_from, end_date=valid_to) for free in free_contracts: self._order.owner_organization.acquired_offerings.append(free.offering.pk) self._order.owner_organization.save() self._order.save() self._send_notification(concept, transactions)
def end_charging(self, transactions, concept): """ Process the second step of a payment once the customer has approved the charge :param transactions: List of transactions applied including the total price and the related model :param concept: Concept of the charge, it can be initial, renovation, or use """ # Update purchase state if self._order.state == 'pending': self._order.state = 'paid' self._order.save() time_stamp = datetime.utcnow() self._order.pending_payment = {} invoice_builder = InvoiceBuilder(self._order) billing_client = BillingClient() if concept != 'initial' else None for transaction in transactions: contract = self._order.get_item_contract(transaction['item']) contract.last_charge = time_stamp valid_from, valid_to = self.end_processors[concept](contract, transaction) # If the customer has been charged create the CDR cdr_manager = CDRManager(self._order, contract) cdr_manager.generate_cdr(transaction['related_model'], time_stamp.isoformat() + 'Z') # Generate the invoice invoice_path = '' try: invoice_path = invoice_builder.generate_invoice(contract, transaction, concept) except: pass # Update contracts charge = Charge( date=time_stamp, cost=transaction['price'], duty_free=transaction['duty_free'], currency=transaction['currency'], concept=concept, invoice=invoice_path ) contract.charges.append(charge) # Send the charge to the billing API to allow user accesses if concept != 'initial': # When the change concept is initial, the product has not been yet created in the inventory billing_client.create_charge(charge, contract.product_id, start_date=valid_from, end_date=valid_to) self._order.save() # TODO: Improve the rollback in case of unexpected exception try: # Send notifications if required handler = NotificationsHandler() if concept == 'initial': # Send customer and provider notifications handler.send_acquired_notification(self._order) for cont in self._order.contracts: handler.send_provider_notification(self._order, cont) elif concept == 'recurring' or concept == 'usage': handler.send_renovation_notification(self._order, transactions) except: pass