From f6a9ce622cb749f32c5ab98a1b3afba59fa7b518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Mon, 3 Jan 2022 17:38:50 +0100 Subject: [PATCH] Add component parameter forms --- shimatta_kenkyusho/api/serializers.py | 1 + shimatta_kenkyusho/api/views.py | 2 +- shimatta_kenkyusho/parts/forms.py | 46 ++++++++++++++++++- .../migrations/0010_auto_20220103_1606.py | 25 ++++++++++ shimatta_kenkyusho/parts/models.py | 23 +++++++++- shimatta_kenkyusho/parts/views.py | 27 +++++++++++ .../templates/parts/components-detail.html | 28 ++++++++++- .../modals/new-component-parameter-modal.html | 26 +++++++++++ 8 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 shimatta_kenkyusho/parts/migrations/0010_auto_20220103_1606.py create mode 100644 shimatta_kenkyusho/templates/parts/modals/new-component-parameter-modal.html diff --git a/shimatta_kenkyusho/api/serializers.py b/shimatta_kenkyusho/api/serializers.py index c3d6f29..ffb405f 100644 --- a/shimatta_kenkyusho/api/serializers.py +++ b/shimatta_kenkyusho/api/serializers.py @@ -73,6 +73,7 @@ class ComponentTypeSerializer(serializers.HyperlinkedModelSerializer): class ComponentParameterTypeSerializer(serializers.HyperlinkedModelSerializer): id = serializers.ReadOnlyField() + descriptive_name = serializers.ReadOnlyField() class Meta: model = parts_models.ComponentParameterType fields = '__all__' \ No newline at end of file diff --git a/shimatta_kenkyusho/api/views.py b/shimatta_kenkyusho/api/views.py index ede5fef..fce8f85 100644 --- a/shimatta_kenkyusho/api/views.py +++ b/shimatta_kenkyusho/api/views.py @@ -65,7 +65,7 @@ class PartsComponentParameterTypeViewSet(viewsets.ModelViewSet): serializer_class = ComponentParameterTypeSerializer permission_classes = [permissions.DjangoModelPermissions] filter_backends = [filters.SearchFilter] - search_fields = ['parameter_name'] + search_fields = ['parameter_name', 'unit'] class PartsManufacturerViewSet(viewsets.ModelViewSet): queryset = parts_models.Manufacturer.objects.all() diff --git a/shimatta_kenkyusho/parts/forms.py b/shimatta_kenkyusho/parts/forms.py index 93f6a52..e33173b 100644 --- a/shimatta_kenkyusho/parts/forms.py +++ b/shimatta_kenkyusho/parts/forms.py @@ -220,6 +220,17 @@ class DistributorNumberDeleteForm(forms.Form): raise ValidationError('distributor number invalid') return distributor_number +class ComponentParameterDeleteForm(forms.Form): + param_num = forms.UUIDField(required=True) + + def clean_param_num(self): + my_uuid = self.cleaned_data['param_num'] + try: + param = parts_models.ComponentParameter.objects.get(id=my_uuid) + except: + raise ValidationError('Parameter Number Invalid') + return param + class AdvancedComponentSearchForm(forms.Form): name = forms.CharField(max_length=255, label='Component Name', required=False) package = AutocompleteForeingKeyField(required=False, api_search_url='package-list', foreign_model=parts_models.Package) @@ -264,4 +275,37 @@ class ComponentParameterSearchForm(forms.Form): Column('parameter'), Column('value') ) - ) \ No newline at end of file + ) +class ComponentParameterCreateForm(forms.Form): + parameter_type = AutocompleteForeingKeyField(required=True, foreign_model=parts_models.ComponentParameterType, api_search_url='componentparametertype-list', image_field_name=None, name_field_name='descriptive_name') + value = forms.CharField(required=True, max_length=256) + + def clean(self): + data = super().clean() + ptype = data.get('parameter_type') + value = data.get('value') + + if not ptype: + raise ValidationError('No valid parameter type selected') + + if not value: + raise ValidationError('No valid parameter value') + + if ptype.parameter_type == 'E' or ptype.parameter_type == 'I' or ptype.parameter_type == 'N': + try: + number = EngineeringNumberConverter.engineering_to_number(value) + except: + raise ValidationError('Cannot convert value to number') + data['number_value'] = number + else: + pass + + def save(self, component): + param_type = self.cleaned_data['parameter_type'] + if param_type.parameter_type == 'F': + text_value = self.cleaned_data['value'] + value = 0 + else: + text_value = '' + value = self.cleaned_data['number_value'] + parts_models.ComponentParameter.objects.create(parameter_type=param_type, component=component, value=value, text_value=text_value) diff --git a/shimatta_kenkyusho/parts/migrations/0010_auto_20220103_1606.py b/shimatta_kenkyusho/parts/migrations/0010_auto_20220103_1606.py new file mode 100644 index 0000000..5ee32dc --- /dev/null +++ b/shimatta_kenkyusho/parts/migrations/0010_auto_20220103_1606.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.5 on 2022-01-03 16:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('parts', '0009_auto_20220101_1306'), + ] + + operations = [ + migrations.AlterField( + model_name='componentparametertype', + name='parameter_description', + field=models.TextField(blank=True, default=''), + preserve_default=False, + ), + migrations.AlterField( + model_name='componentparametertype', + name='unit', + field=models.CharField(blank=True, default='', max_length=10), + preserve_default=False, + ), + ] diff --git a/shimatta_kenkyusho/parts/models.py b/shimatta_kenkyusho/parts/models.py index 62704f0..21994b0 100644 --- a/shimatta_kenkyusho/parts/models.py +++ b/shimatta_kenkyusho/parts/models.py @@ -8,6 +8,7 @@ from django.dispatch import receiver from django.core.validators import MinValueValidator, MaxValueValidator import os import uuid +from shimatta_modules.EngineeringNumberConverter import EngineeringNumberConverter as NumConv storage_name_validator = RegexValidator(r'^[^/]*$', 'Slashes are not allowed in storage names') @@ -26,8 +27,8 @@ class ComponentParameterType(models.Model): ) parameter_name = models.CharField(max_length=50, unique=True) - parameter_description = models.TextField(null=True, blank=True) - unit = models.CharField(max_length=10, null=True, blank=True) + parameter_description = models.TextField(null=False, blank=True) + unit = models.CharField(max_length=10, null=False, blank=True) parameter_type = models.CharField(max_length=1, choices=TYPE_CHOICES, default='N') def __str__(self): @@ -35,6 +36,12 @@ class ComponentParameterType(models.Model): if self.unit: unit = ' in ' + self.unit return self.parameter_name + unit + ' | ' + self.get_parameter_type_display() + + def descriptive_name(self): + if self.unit: + return f'{self.parameter_name} [{self.unit}]' + else: + return self.parameter_name class ComponentType(models.Model): class Meta: @@ -218,6 +225,18 @@ class ComponentParameter(models.Model): return str(self.component)+ ': '+ str(self.parameter_type) + ': ' + value + def resolved_value_as_string(self): + my_type = self.parameter_type.parameter_type + + if my_type == 'E' or my_type == 'I': + # Engineering float number + (num, prefix) = NumConv.number_to_engineering(self.value, it_unit=(True if my_type=='I' else False)) + return f'{num} {prefix}{self.parameter_type.unit}' + elif my_type == 'N': + # Standard float number + return f'{self.value} {self.parameter_type.unit}' + elif my_type == 'F': + return self.text_value class Stock(models.Model): class Meta: diff --git a/shimatta_kenkyusho/parts/views.py b/shimatta_kenkyusho/parts/views.py index fa410d0..b8cd448 100644 --- a/shimatta_kenkyusho/parts/views.py +++ b/shimatta_kenkyusho/parts/views.py @@ -622,7 +622,9 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): context['stocks'] = Stock.objects.filter(component=self.object) context['comp_form'] = ComponentForm(instance=self.object) context['new_distri_num_form'] = DistributorNumberCreateForm() + context['new_param_form'] = ComponentParameterCreateForm() context['distri_nums'] = DistributorNum.objects.filter(component=self.object) + context['parameters'] = ComponentParameter.objects.filter(component=self.object) return context @@ -679,6 +681,27 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): context = self.get_context_data(**kwargs) return self.render_to_response(context) + + def handle_submit_delete_param_post(self, request, **kwargs): + form = ComponentParameterDeleteForm(data=request.POST) + if form.is_valid(): + form.cleaned_data['param_num'].delete() + + context = self.get_context_data(**kwargs) + return self.render_to_response(context) + + def handle_submit_new_param_post(self, request, **kwargs): + form = ComponentParameterCreateForm(data=request.POST) + + if form.is_valid(): + try: + form.save(self.object) + except IntegrityError: + form.add_error('__all__', 'This parameter is already set') + context = self.get_context_data(**kwargs) + if not form.is_valid(): + context['new_param_form'] = form + return self.render_to_response(context) def post(self, request, *args, **kwargs): self.object = self.get_object() @@ -690,6 +713,10 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView): return self.handle_submit_new_distri_num_post(request, **kwargs) elif 'submit-delete-distributor-num' in request.POST: return self.handle_submit_delete_distri_num_post(request, **kwargs) + elif 'submit-delete-param' in request.POST: + return self.handle_submit_delete_param_post(request, **kwargs) + elif 'submit-create-new-param' in request.POST: + return self.handle_submit_new_param_post(request, **kwargs) else: return super().post(request, *args, **kwargs) diff --git a/shimatta_kenkyusho/templates/parts/components-detail.html b/shimatta_kenkyusho/templates/parts/components-detail.html index 5d758b2..e865118 100644 --- a/shimatta_kenkyusho/templates/parts/components-detail.html +++ b/shimatta_kenkyusho/templates/parts/components-detail.html @@ -95,7 +95,29 @@
-

Parameters

+

Parameters

+ + + + + + + + {% for param in parameters %} + + + + + {% endfor %} + +
ParameterValue
{{param.parameter_type.parameter_name}}{{param.resolved_value_as_string}} +
+ {% csrf_token %} + + +
+
+

Distributor Part Numbers

@@ -204,6 +226,7 @@ {% include 'parts/modals/new-distributor-number-modal.html' with component_name=component.name form=new_distri_num_form %} {% include 'parts/modals/edit-component-modal.html' with heading="Edit "|add:component.name form=comp_form %} +{% include 'parts/modals/new-component-parameter-modal.html' with component_name=component.name form=new_param_form %} {% endblock content %} {% block custom_scripts %} @@ -218,6 +241,9 @@ bootstrap.Modal.getOrCreateInstance(document.getElementById('component-delete-mo {% if new_distri_num_form.errors %} bootstrap.Modal.getOrCreateInstance(document.getElementById('new-distributor-number-modal')).show(); {% endif %} +{% if new_param_form.errors %} +bootstrap.Modal.getOrCreateInstance(document.getElementById('new-component-parameter-modal')).show(); +{% endif %} {% endblock custom_scripts %} diff --git a/shimatta_kenkyusho/templates/parts/modals/new-component-parameter-modal.html b/shimatta_kenkyusho/templates/parts/modals/new-component-parameter-modal.html new file mode 100644 index 0000000..dae9f55 --- /dev/null +++ b/shimatta_kenkyusho/templates/parts/modals/new-component-parameter-modal.html @@ -0,0 +1,26 @@ +{% comment "" %} +Needs: +- form : ComponentParameterCreateForm +- component_name: Component's name + +{% endcomment %} +{% load crispy_forms_tags %} + \ No newline at end of file