Add component parameter forms

This commit is contained in:
Mario Hüttel 2022-01-03 17:38:50 +01:00
parent cab865c8fe
commit f6a9ce622c
8 changed files with 173 additions and 5 deletions

View File

@ -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__'

View File

@ -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()

View File

@ -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)
@ -265,3 +276,36 @@ class ComponentParameterSearchForm(forms.Form):
Column('value')
)
)
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)

View File

@ -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,
),
]

View File

@ -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):
@ -36,6 +37,12 @@ class ComponentParameterType(models.Model):
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:
ordering = ['class_name']
@ -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:

View File

@ -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
@ -680,6 +682,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()
if 'submit-edit-component' in request.POST:
@ -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)

View File

@ -95,7 +95,29 @@
</div>
<div class="row">
<div class="col">
<h3>Parameters</h3>
<h3>Parameters <button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#new-component-parameter-modal"><i class="bi bi-plus-circle"></i></button></h3>
<table class="table">
<thead>
<th scope="col">Parameter</th>
<th scope="col">Value</th>
<th scope="col"></th>
</thead>
<tbody>
{% for param in parameters %}
<tr>
<td>{{param.parameter_type.parameter_name}}</td>
<td>{{param.resolved_value_as_string}}</td>
<td>
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{param.id}}" name="param_num">
<button class="btn btn-danger" name="submit-delete-param">X</button>
</form>
<td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col">
<h3>Distributor Part Numbers <button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#new-distributor-number-modal"><i class="bi bi-plus-circle"></i></button></h3>
@ -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 %}
</script>
{% endblock custom_scripts %}

View File

@ -0,0 +1,26 @@
{% comment "" %}
Needs:
- form : ComponentParameterCreateForm
- component_name: Component's name
{% endcomment %}
{% load crispy_forms_tags %}
<div class="modal fade" id="new-component-parameter-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Parameter for {{component_name}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form action="" method="post">
{% csrf_token %}
<div class="modal-body">
{{form|crispy}}
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Add Number" name="submit-create-new-param">
</div>
</form>
</div>
</div>
</div>