def validate(self, attrs): offering = attrs['offering'] plan = attrs.get('plan') if plan: if plan.offering != offering: raise rf_exceptions.ValidationError({ 'plan': _('This plan is not available for selected offering.') }) if offering.options: validate_options(offering.options['options'], attrs.get('attributes')) limits = attrs.get('limits') if limits: valid_component_types = offering.components \ .filter(billing_type=models.OfferingComponent.BillingTypes.USAGE) \ .values_list('type', flat=True) invalid_types = set(limits.keys()) - set(valid_component_types) if invalid_types: raise ValidationError({ 'limits': _('Invalid types: %s') % ', '.join(invalid_types) }) return attrs
def validate(self, attrs): offering = attrs['offering'] plan = attrs.get('plan') if plan: if plan.offering != offering: raise rf_exceptions.ValidationError({ 'plan': _('This plan is not available for selected offering.') }) if offering.options: validate_options(offering.options['options'], attrs.get('attributes')) return attrs
def create(self, validated_data): """ Each offering corresponds to the single issue which has next values: 'project' - a hyperlinked field which must be provided with every request; 'customer' - customer is extracted from the provided project; 'caller' - a user who sent a request is considered to be a 'caller' of the issue; 'summary' - has a format of 'Request for <template_name>' or 'Request for "Support" if empty; 'description' - combined list of all other fields provided with the request; """ template = validated_data['template'] plan = validated_data.pop('plan', None) # Temporary code for backward compatibility if not plan: plan = template.plans.first() # It's okay if there's no plan. if plan and plan.template != template: raise serializers.ValidationError({ 'plan': _('Plan should be related to the same template.'), }) attributes = validated_data.get('attributes', {}) if isinstance(template.config, dict) and template.config.get('options'): try: validate_options(template.config['options'], attributes) except serializers.ValidationError as exc: raise serializers.ValidationError({'attributes': exc}) else: validated_data.update(attributes) offering_configuration = template.config issue_details = self._get_issue_details(validated_data) issue_details['summary'] = render_issue_template('summary', issue_details) issue_details['description'] = render_issue_template('description', issue_details) issue = models.Issue.objects.create(**issue_details) payload = dict( issue=issue, project=issue.project, name=validated_data.get('name'), template=template, ) if plan: payload.update(dict( product_code=plan.product_code, article_code=plan.article_code, unit_price=plan.unit_price, unit=plan.unit, plan=plan, )) else: # Temporary workaround for backward compatibility payload.update(dict( product_code=offering_configuration.get('product_code', ''), article_code=offering_configuration.get('article_code', ''), )) offering = models.Offering.objects.create(**payload) return offering
def create(self, validated_data): """ Each offering corresponds to the single issue which has next values: 'project' - a hyperlinked field which must be provided with every request; 'customer' - customer is extracted from the provided project; 'caller' - a user who sent a request is considered to be a 'caller' of the issue; 'summary' - has a format of 'Request for <template_name>' or 'Request for "Support" if empty; 'description' - combined list of all other fields provided with the request; """ project = validated_data['project'] template = validated_data['template'] plan = validated_data.pop('plan', None) # Temporary code for backward compatibility if not plan: plan = template.plans.first() # It's okay if there's no plan. if plan and plan.template != template: raise serializers.ValidationError({ 'plan': _('Plan should be related to the same template.'), }) attributes = validated_data.get('attributes') if attributes: if not isinstance(template.config, dict) or not(template.config.get('options')): raise serializers.ValidationError({'attributes': _('Extra attributes are not allowed.')}) try: validate_options(template.config['options'], attributes) except serializers.ValidationError as exc: raise serializers.ValidationError({'attributes': exc}) else: validated_data.update(attributes) else: if template.config.get('options'): raise serializers.ValidationError({ 'attributes': _('This field is required.'), }) offering_configuration = template.config type_label = offering_configuration.get('label', template.name) issue_details = dict( caller=self.context['request'].user, project=project, customer=project.customer, type=settings.WALDUR_SUPPORT['DEFAULT_OFFERING_ISSUE_TYPE'], summary='Request for \'%s\'' % type_label, description=self._form_description(offering_configuration, validated_data)) issue_details['summary'] = render_issue_template('summary', issue_details) issue_details['description'] = render_issue_template('description', issue_details) issue = models.Issue.objects.create(**issue_details) payload = dict( issue=issue, project=issue.project, name=validated_data.get('name'), template=template, ) if plan: payload.update(dict( product_code=plan.product_code, article_code=plan.article_code, unit_price=plan.unit_price, unit=plan.unit, )) offering = models.Offering.objects.create(**payload) return offering