Esempio n. 1
0
    def create(self, request):
        try:
            # Extract SDR document from the HTTP request
            data = json.loads(request.body)
        except:
            # The usage document is not valid, so the state cannot be changed
            return build_response(request, 400, 'The request does not contain a valid JSON object')

        # Validate usage information
        response = None
        try:
            sdr_manager = SDRManager()
            sdr_manager.validate_sdr(data)
        except PermissionDenied as e:
            response = build_response(request, 403, unicode(e))
        except ValueError as e:
            response = build_response(request, 422, unicode(e))
        except:
            response = build_response(request, 500, 'The SDR document could not be processed due to an unexpected error')

        usage_client = UsageClient()
        if response is not None:
            # The usage document is not valid, change its state to Rejected
            usage_client.update_usage_state('Rejected', data)
        else:
            # The usage document is valid, change its state to Guided
            usage_client.update_usage_state('Guided', data)
            response = build_response(request, 200, 'OK')

        # Update usage document state
        return response
    def _process_use_charge(self, contracts):
        """
        Resolves usage charges, which includes pay-per-use payments
        :return: The URL where redirecting the customer to approve the charge
        """
        self._order.state = 'pending'

        transactions = []
        usage_client = UsageClient()
        for contract in contracts:
            if 'pay_per_use' not in contract.pricing_model:
                continue

            related_model = {
                'pay_per_use': contract.pricing_model['pay_per_use']
            }

            accounting = self._parse_raw_accounting(usage_client.get_customer_usage(
                self._order.owner_organization.name, contract.product_id, state='Guided'))

            if 'alteration' in contract.pricing_model and \
               contract.pricing_model['alteration'].get('period') == 'recurring':
                related_model['alteration'] = contract.pricing_model['alteration']

            if len(accounting) > 0:
                self._append_transaction(
                    transactions,
                    contract,
                    related_model,
                    accounting=accounting
                )

        return self._execute_renovation_transactions(transactions, 'There is not usage payments to renovate')
    def _process_use_charge(self, contracts):
        """
        Resolves usage charges, which includes pay-per-use payments
        :return: The URL where redirecting the customer to approve the charge
        """
        self._order.state = 'pending'

        transactions = []
        usage_client = UsageClient()
        for contract in contracts:
            if 'pay_per_use' not in contract.pricing_model:
                continue

            related_model = {
                'pay_per_use': contract.pricing_model['pay_per_use']
            }

            accounting = self._parse_raw_accounting(usage_client.get_customer_usage(
                self._order.owner_organization.name, contract.product_id, state='Guided'))

            if 'alteration' in contract.pricing_model and \
               contract.pricing_model['alteration'].get('period') == 'recurring':
                related_model['alteration'] = contract.pricing_model['alteration']

            if len(accounting) > 0:
                self._append_transaction(
                    transactions,
                    contract,
                    related_model,
                    accounting=accounting
                )

        return self._execute_renovation_transactions(transactions, 'There is not usage payments to renovate')
Esempio n. 4
0
    def remove_usage_specs(self):
        if 'usage' in self._model.options:
            try:
                usage_client = UsageClient()

                for unit, href in self._model.options['usage'].iteritems():
                    spec_id = href.split('/')[-1]
                    usage_client.delete_usage_spec(spec_id)
            except HTTPError as e:
                if e.response.status_code != 404:
                    raise e
Esempio n. 5
0
    def _end_use_charge(self, contract, transaction):
        # Change applied usage documents SDR Guided to Rated
        usage_client = UsageClient()
        for sdr_info in transaction['applied_accounting']:
            for sdr in sdr_info['accounting']:

                usage_client.rate_usage(
                    sdr['usage_id'],
                    unicode(contract.last_charge),
                    sdr['duty_free'],
                    sdr['price'],
                    sdr_info['model']['tax_rate'],
                    transaction['currency'],
                    contract.product_id
                )

        transaction['related_model']['accounting'] = transaction['applied_accounting']
Esempio n. 6
0
    def configure_usage_spec(self):
        # Build common usage spec
        specification_template = {
            'usageSpecCharacteristic': [
                self._get_usage_characteristic('orderId', 'Order identifier',
                                               'string'),
                self._get_usage_characteristic('productId',
                                               'Product identifier', 'string'),
                self._get_usage_characteristic(
                    'correlationNumber', 'Accounting correlation number',
                    'number'),
                self._get_usage_characteristic('unit', 'Accounting unit',
                                               'string'),
                self._get_usage_characteristic('value', 'Accounting value',
                                               'number')
            ]
        }

        usage_specs = self.get_usage_specs()
        usage_client = UsageClient()

        # Create usage specifications for supported units
        for spec in usage_specs:
            if 'name' not in spec or 'description' not in spec:
                raise PluginError(
                    'Invalid product specification configuration, must include name and description'
                )

            # Check if the usage spec is already registered
            if 'usage' not in self._model.options or spec['name'].lower(
            ) not in self._model.options['usage']:
                usage_spec = deepcopy(specification_template)
                usage_spec['name'] = spec['name']
                usage_spec['description'] = spec['description']
                created_spec = usage_client.create_usage_spec(usage_spec)

                if 'usage' not in self._model.options:
                    self._model.options['usage'] = {}

                # Save the spec href to be used in usage documents
                self._model.options['usage'][
                    spec['name'].lower()] = created_spec['href']
                self._model.save()
Esempio n. 7
0
    def _end_use_charge(self, contract, transaction):
        # Change applied usage documents SDR Guided to Rated
        usage_client = UsageClient()

        for sdr_info in transaction['applied_accounting']:
            for sdr in sdr_info['accounting']:

                usage_client.rate_usage(sdr['usage_id'],
                                        unicode(contract.last_charge),
                                        sdr['duty_free'], sdr['price'],
                                        sdr_info['model']['tax_rate'],
                                        transaction['currency'],
                                        contract.product_id)

        transaction['related_model']['accounting'] = transaction[
            'applied_accounting']

        return contract.charges[-1].date if len(
            contract.charges) > 0 else self._order.date, None
Esempio n. 8
0
    def create(self, request):
        try:
            # Extract SDR document from the HTTP request
            data = json.loads(request.body)
        except:
            # The usage document is not valid, so the state cannot be changed
            return build_response(
                request, 400,
                'The request does not contain a valid JSON object')

        # Validate usage information
        response = None
        sdr_manager = SDRManager()
        try:
            sdr_manager.validate_sdr(data)
        except PermissionDenied as e:
            response = build_response(request, 403, str(e))
        except ValueError as e:
            response = build_response(request, 422, str(e))
        except:
            response = build_response(
                request, 500,
                'The SDR document could not be processed due to an unexpected error'
            )

        usage_client = UsageClient()
        if response is not None:
            # The usage document is not valid, change its state to Rejected
            usage_client.update_usage_state(data['id'], 'Rejected')
        else:
            # The usage document is valid, change its state to Guided
            usage_client.update_usage_state(data['id'], 'Guided')
            sdr_manager.update_usage()
            response = build_response(request, 200, 'OK')

        # Update usage document state
        return response
Esempio n. 9
0
    def on_usage_refresh(self, asset, contract, order):
        if not self._model.pull_accounting:
            return

        pending_accounting, last_usage = self.get_pending_accounting(
            asset, contract, order)
        usage_template = {
            'type':
            'event',
            'status':
            'Received',
            'usageCharacteristic': [{
                'name': 'orderId',
                'value': order.order_id
            }, {
                'name': 'productId',
                'value': contract.product_id
            }],
            'relatedParty': [{
                'role': 'customer',
                'id': order.owner_organization.name,
                'href': order.owner_organization.get_party_url()
            }]
        }

        usage_client = UsageClient()
        for usage_record in pending_accounting:
            if 'date' not in usage_record or 'unit' not in usage_record or 'value' not in usage_record:
                raise PluginError(
                    'Invalid usage record, it must include date, unit and value'
                )

            # Generate a TMForum usage document for each usage record
            usage = deepcopy(usage_template)

            usage['date'] = usage_record['date']

            usage['usageSpecification'] = {
                'href': self._model.options['usage'][usage_record['unit']],
                'name': usage_record['unit']
            }

            usage['usageCharacteristic'].append({
                'name': 'unit',
                'value': usage_record['unit']
            })

            usage['usageCharacteristic'].append({
                'name':
                'correlationNumber',
                'value':
                contract.correlation_number
            })

            usage['usageCharacteristic'].append({
                'name': 'value',
                'value': usage_record['value']
            })

            usage_doc = usage_client.create_usage(usage)
            # All the  information is known so the document is directly created in Guided state
            usage_client.update_usage_state(usage_doc['id'], 'Guided')

            contract.correlation_number += 1
            order.save()

        if last_usage is not None:
            contract.last_usage = last_usage
            order.save()