def _process_delete_items(self, items):
        for item in items:
            if 'product' not in item:
                raise OrderingError(
                    'It is required to specify product information in delete order items'
                )

            product = item['product']

            if 'id' not in product:
                raise OrderingError(
                    'It is required to provide product id in delete order items'
                )

            # Set the contract as terminated
            client = InventoryClient()
            order, contract = self._get_existing_contract(
                client, product['id'])

            # Suspend the access to the service
            on_product_suspended(order, contract)

            contract.terminated = True
            order.save()

            # Terminate product in the inventory
            client.terminate_product(product['id'])
    def create(self, request):
        task, order, contract, error_response = validate_product_job(
            self, request)

        if error_response is not None:
            return error_response

        # If the model is pay-per-use charge for pending payment
        redirect_url = None
        if task['priceType'].lower() == 'usage':
            # The update of the product status need to be postponed if there is a pending payment
            redirect_url, error_response = process_product_payment(
                self, request, task, order, contract)

            if error_response is not None:
                return error_response

        response = build_response(request, 200, 'OK')

        # Include redirection header if needed
        if redirect_url is not None:
            response['X-Redirect-URL'] = redirect_url
        else:
            # Suspend the product as no pending payment
            on_product_suspended(order, contract)

            contract.suspended = True
            order.save()

            client = InventoryClient()
            client.suspend_product(contract.product_id)

        return response
    def test_product_suspended(self):
        self._contract.offering = self._get_offering_mock()

        decorators.on_product_suspended(self._order, self._contract)

        decorators.load_plugin_module.assert_called_once_with('asset')
        self._module.on_product_suspension.assert_called_once_with(
            self._contract.offering.asset, self._contract, self._order)
    def test_product_suspended(self):
        self._contract.offering = '61004aba5e05acc115f022f0'
        offering = self._get_offering_mock()

        decorators.Offering = MagicMock()
        decorators.Offering.objects.get.return_value = offering

        decorators.on_product_suspended(self._order, self._contract)

        decorators.Offering.objects.get.assert_called_once_with(
            pk=ObjectId('61004aba5e05acc115f022f0'))
        decorators.load_plugin_module.assert_called_once_with('asset')
        self._module.on_product_suspension.assert_called_once_with(
            offering.asset, self._contract, self._order)
    def _check_renovation_date(self, renovation_date, order, contract):
        now = datetime.utcnow()

        timed = renovation_date - now

        if timed.days < 7:
            handler = NotificationsHandler()

            if timed.days < 0:
                # Suspend the access to the service
                on_product_suspended(order, contract)

                # Notify that the subscription has finished
                handler.send_payment_required_notification(order, contract)

                # Set the product as suspended
                client = InventoryClient()
                client.suspend_product(contract.product_id)

            else:
                # There is less than a week remaining
                handler.send_near_expiration_notification(order, contract, timed.days)
    def _process_delete_items(self, items):
        for item in items:
            if 'product' not in item:
                raise OrderingError('It is required to specify product information in delete order items')

            product = item['product']

            if 'id' not in product:
                raise OrderingError('It is required to provide product id in delete order items')

            # Set the contract as terminated
            client = InventoryClient()
            order, contract = self._get_existing_contract(client, product['id'])

            # Suspend the access to the service
            on_product_suspended(order, contract)

            contract.terminated = True
            order.save()

            # Terminate product in the inventory
            client.terminate_product(product['id'])
    def _check_renovation_date(self, renovation_date, order, contract):
        now = datetime.utcnow()

        timed = renovation_date - now

        if timed.days < 7:
            handler = NotificationsHandler()

            if timed.days < 0:
                # Suspend the access to the service
                on_product_suspended(order, contract)

                # Notify that the subscription has finished
                handler.send_payment_required_notification(order, contract)

                # Set the product as suspended
                client = InventoryClient()
                client.suspend_product(contract.product_id)

            else:
                # There is less than a week remaining
                handler.send_near_expiration_notification(
                    order, contract, timed.days)