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