def create(self, request):
        # In case the user cancels the payment is necessary to update
        # the database in order to avoid an inconsistent state
        try:
            data = json.loads(request.body)
            order = Order.objects.get(order_id=data['orderId'])

            # Get the payment client
            # Load payment client
            cln_str = settings.PAYMENT_CLIENT
            client_package, client_class = cln_str.rsplit('.', 1)

            payment_client = getattr(importlib.import_module(client_package), client_class)

            # build the payment client
            client = payment_client(order)

            for sale in order.sales_ids:
                client.refund(sale)

            # Only those orders with all its order items in ack state can be refunded
            # that means that all the contracts have been refunded
            for contract in order.contracts:
                if len(contract.charges) > 0:
                    cdr_manager = CDRManager(order, contract)
                    charge = contract.charges[-1]

                    # Create a refund CDR for each contract
                    cdr_manager.refund_cdrs(charge['cost'], charge['duty_free'], charge['date'].isoformat() + 'Z')

            order.delete()
        except:
            return build_response(request, 400, 'Sales cannot be refunded')

        return build_response(request, 200, 'Ok')
    def create(self, request):
        # In case the user cancels the payment is necessary to update
        # the database in order to avoid an inconsistent state
        try:
            data = json.loads(request.body)
            order = Order.objects.get(order_id=data['orderId'])

            # Get the payment client
            # Load payment client
            cln_str = settings.PAYMENT_CLIENT
            client_package, client_class = cln_str.rsplit('.', 1)

            payment_client = getattr(importlib.import_module(client_package), client_class)

            # build the payment client
            client = payment_client(order)

            for sale in order.sales_ids:
                client.refund(sale)

            # Only those orders with all its order items in ack state can be refunded
            # that means that all the contracts have been refunded
            for contract in order.contracts:
                cdr_manager = CDRManager(order, contract)
                charge = contract.charges[-1]

                cdr_manager.refund_cdrs(charge['cost'], charge['duty_free'], charge['date'].isoformat() + 'Z')

            # Create a refund CDR for each contract
            order.delete()
        except:
            return build_response(request, 400, 'Sales cannot be refunded')

        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)
Exemple #4
0
    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.now()

        self._order.pending_payment = {}

        for transaction in transactions:
            contract = self._order.get_item_contract(transaction['item'])
            # Update contracts
            contract.charges.append({
                'date': time_stamp,
                'cost': transaction['price'],
                'currency': transaction['currency'],
                'concept': concept
            })

            contract.last_charge = time_stamp

            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'], unicode(time_stamp))

        self._order.save()

        # TODO: Improve the rollback in case of unexpected exception
        try:
            # Generate the invoice
            invoice_builder = InvoiceBuilder(self._order)
            invoice_builder.generate_invoice(transactions, concept)

            # 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 == 'renovation' or concept == 'use':
                handler.send_renovation_notification(self._order, transactions)
        except:
            pass
    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