Do some random coding for Distribotr numbers and Component parameters. This is probably not the most ideal solution. Will change this later

This commit is contained in:
Mario Hüttel 2021-11-13 21:05:52 +01:00
parent 5c3197e040
commit ac318ca864
6 changed files with 277 additions and 57 deletions

View File

@ -183,9 +183,25 @@ class EditComponentForm(forms.Form):
raise ValidationError('Invalid Package') raise ValidationError('Invalid Package')
def _save_new(self):
self.instance = parts_models.Component.objects.create(
name=self.cleaned_data['name'],
datasheet_link=self.cleaned_data['datasheet_link'],
description=self.cleaned_data['description'],
package=self.cleaned_data['package_object'],
component_type=self.cleaned_data['component_type_object'],
pref_distri=self.cleaned_data['pref_distri_object'],
manufacturer=self.cleaned_data['manufacturer_object']
)
if bool(self.cleaned_data['image']):
self.instance.image = self.cleaned_data['image']
self.instance.save()
def save(self): def save(self):
if self.instance is None: if self.instance is None:
self.instance = parts_models.Component.objects.create() self._save_new()
return
self.instance.name = self.cleaned_data['name'] self.instance.name = self.cleaned_data['name']
self.instance.datasheet_link = self.cleaned_data['datasheet_link'] self.instance.datasheet_link = self.cleaned_data['datasheet_link']
@ -203,8 +219,8 @@ class EditComponentForm(forms.Form):
self.instance.save() self.instance.save()
class EditComponentParameterForm(forms.Form): class EditComponentParameterForm(forms.Form):
parameter_type = forms.CharField() # This must come first. Do not change the order of these elements! parameter_type = forms.CharField(initial='') # This must come first. Do not change the order of these elements!
value = forms.CharField() value = forms.CharField(initial='')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -215,12 +231,12 @@ class EditComponentParameterForm(forms.Form):
self.parameter_type_object = type_instance self.parameter_type_object = type_instance
kwargs['initial']['parameter_type'] = init_values['parameter_type'].parameter_name kwargs['initial']['parameter_type'] = init_values['parameter_type'].parameter_name
if isinstance(init_values['value'], int) or isinstance(init_values['value'], float): if isinstance(init_values['value'], int) or isinstance(init_values['value'], float):
if type_instance.engineering_unit: if type_instance.parameter_type == 'E':
(num, prefix) = EngineeringNumberConverter.number_to_engineering(init_values['value'], False) (num, prefix) = EngineeringNumberConverter.number_to_engineering(init_values['value'], False)
kwargs['initial']['value'] = f'{num} {prefix}' kwargs['initial']['value'] = f'{num}{prefix}'
elif type_instance.it_unit: elif type_instance.parameter_type == 'I':
(num, prefix) = EngineeringNumberConverter.number_to_engineering(init_values['value'], True) (num, prefix) = EngineeringNumberConverter.number_to_engineering(init_values['value'], True)
kwargs['initial']['value'] = f'{num} {prefix}' kwargs['initial']['value'] = f'{num}{prefix}'
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -245,12 +261,12 @@ class EditComponentParameterForm(forms.Form):
processed_value = None processed_value = None
if parameter_type.it_unit or parameter_type.engineering_unit: if parameter_type.parameter_type == 'E' or parameter_type.parameter_type == 'I':
try: try:
processed_value = EngineeringNumberConverter.engineering_to_number(value_data) processed_value = EngineeringNumberConverter.engineering_to_number(value_data)
except: except:
raise ValidationError(f'Cannot not convert Value "{value_data}" to a number') raise ValidationError(f'Cannot not convert Value "{value_data}" to a number')
elif parameter_type.freetext_parameter: elif parameter_type.parameter_type == 'F':
processed_value = value_data processed_value = value_data
else: else:
try: try:
@ -260,4 +276,19 @@ class EditComponentParameterForm(forms.Form):
self.cleaned_data['processed_value'] = processed_value self.cleaned_data['processed_value'] = processed_value
return value_data return value_data
class DistributorNumberForm(forms.ModelForm):
class Meta:
model = parts_models.DistributorNum
fields = ['distributor', 'distributor_part_number']
class DistributorNumberFormSet(forms.BaseModelFormSet):
def save(self, component, commit=True):
instances = super().save(commit=False)
for instance in instances:
instance.component = component
if commit:
instance.save()
return instances

View File

@ -0,0 +1,30 @@
# Generated by Django 3.2 on 2021-11-13 15:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parts', '0003_alter_componentparametertype_unit'),
]
operations = [
migrations.RemoveField(
model_name='componentparametertype',
name='engineering_unit',
),
migrations.RemoveField(
model_name='componentparametertype',
name='freetext_parameter',
),
migrations.RemoveField(
model_name='componentparametertype',
name='it_unit',
),
migrations.AddField(
model_name='componentparametertype',
name='parameter_type',
field=models.CharField(choices=[('F', 'Free Text'), ('N', 'Standard float number'), ('E', 'Engineering / SI Unit'), ('I', 'IT Type')], default='N', max_length=1),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 3.2 on 2021-11-13 19:12
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('parts', '0004_auto_20211113_1508'),
]
operations = [
migrations.AlterModelOptions(
name='distributornum',
options={'ordering': ['distributor__name']},
),
migrations.AlterField(
model_name='componentparameter',
name='value',
field=models.FloatField(default=0),
),
]

View File

@ -17,19 +17,23 @@ class ComponentParameterType(models.Model):
class Meta: class Meta:
ordering = ['parameter_name'] ordering = ['parameter_name']
TYPE_CHOICES = (
('F', 'Free Text'),
('N', 'Standard float number'),
('E', 'Engineering / SI Unit'),
('I', 'IT Type'),
)
parameter_name = models.CharField(max_length=50, unique=True) parameter_name = models.CharField(max_length=50, unique=True)
parameter_description = models.TextField(null=True, blank=True) parameter_description = models.TextField(null=True, blank=True)
unit = models.CharField(max_length=10, null=True, blank=True) unit = models.CharField(max_length=10, null=True, blank=True)
freetext_parameter = models.BooleanField() parameter_type = models.CharField(max_length=1, choices=TYPE_CHOICES, default='N')
engineering_unit = models.BooleanField()
it_unit = models.BooleanField()
def __str__(self): def __str__(self):
unit = self.unit unit = ''
if unit: if self.unit:
return self.parameter_name + ' in ' + unit unit = ' in ' + self.unit
else: return self.parameter_name + unit + ' | ' + self.get_parameter_type_display()
return self.parameter_name
class ComponentType(models.Model): class ComponentType(models.Model):
class Meta: class Meta:
@ -202,11 +206,16 @@ class ComponentParameter(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
component = models.ForeignKey(Component, on_delete=models.CASCADE) # A target component is required! component = models.ForeignKey(Component, on_delete=models.CASCADE) # A target component is required!
parameter_type = models.ForeignKey(ComponentParameterType, on_delete=models.CASCADE) parameter_type = models.ForeignKey(ComponentParameterType, on_delete=models.CASCADE)
value = models.FloatField() value = models.FloatField(default=0)
text_value = models.TextField(null=True, blank=True) text_value = models.TextField(null=True, blank=True)
def __str__(self): def __str__(self):
return str(self.parameter_type) + ': ' + str(self.value) if self.parameter_type.parameter_type == 'F':
value = self.text_value
else:
value = str(self.value)
return str(self.component)+ ': '+ str(self.parameter_type) + ': ' + value
class Stock(models.Model): class Stock(models.Model):
@ -247,7 +256,7 @@ class Stock(models.Model):
class DistributorNum(models.Model): class DistributorNum(models.Model):
class Meta: class Meta:
unique_together = ('component', 'distributor') unique_together = ('component', 'distributor')
ordering = ['distributor_part_number'] ordering = ['distributor__name']
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
distributor_part_number = models.CharField(max_length=100) distributor_part_number = models.CharField(max_length=100)
distributor = models.ForeignKey(Distributor, on_delete=models.CASCADE) distributor = models.ForeignKey(Distributor, on_delete=models.CASCADE)

View File

@ -11,12 +11,12 @@ from django.views import View
import django.forms as forms import django.forms as forms
from django.views.generic import TemplateView, DetailView from django.views.generic import TemplateView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from .models import Storage, Stock, Component, Distributor, Manufacturer, Package, ComponentParameter, ComponentParameterType from .models import Storage, Stock, Component, Distributor, Manufacturer, Package, ComponentParameter, ComponentParameterType, DistributorNum
from .qr_parser import QrCodeValidator from .qr_parser import QrCodeValidator
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import IntegrityError from django.db import IntegrityError
from .forms import MyTestForm, AddSubStorageForm, DeleteStockForm, EditWatermarkForm, EditStockAmountForm, AddStockForm, EditComponentForm, EditComponentParameterForm from .forms import MyTestForm, AddSubStorageForm, DeleteStockForm, EditWatermarkForm, EditStockAmountForm, AddStockForm, EditComponentForm, EditComponentParameterForm, DistributorNumberForm, DistributorNumberFormSet
from django.db.models import Q from django.db.models import Q
from django.db.models.functions import Lower from django.db.models.functions import Lower
import uuid import uuid
@ -391,16 +391,18 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
base_title = '' base_title = ''
navbar_selected = 'Components' navbar_selected = 'Components'
def prepare_initial_param_formset_data(self): def prepare_initial_param_formset_data(self):
parameters = ComponentParameter.objects.filter(component=self.object) parameters = ComponentParameter.objects.filter(component=self.object)
initdata = [] initdata = []
for param in parameters: for param in parameters:
param_type = param.parameter_type param_type = param.parameter_type.parameter_type
if param_type.freetext_parameter: if param_type == 'F':
value = param.text_value value = param.text_value
else: else:
value = param.value value = param.value
initdata.append({'parameter_type': param_type, 'value': value}) initdata.append({'parameter_type': param.parameter_type, 'value': value})
return initdata return initdata
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -409,11 +411,14 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
context['component'] = self.object context['component'] = self.object
context['edit_form'] = EditComponentForm(instance=self.object) context['edit_form'] = EditComponentForm(instance=self.object)
ParameterFormset = forms.formset_factory(EditComponentParameterForm, extra=0, max_num=100) ParameterFormset = forms.formset_factory(EditComponentParameterForm, extra=1, max_num=100, can_delete=True)
context['param_formset'] = ParameterFormset( context['param_formset'] = ParameterFormset(
initial=self.prepare_initial_param_formset_data()) initial=self.prepare_initial_param_formset_data())
context['stocks'] = Stock.objects.filter(component=self.object) context['stocks'] = Stock.objects.filter(component=self.object)
DistriNumFormSet = forms.modelformset_factory(DistributorNum, form=DistributorNumberForm, extra=2)
context['distri_num_formset'] = DistriNumFormSet(queryset=DistributorNum.objects.filter(component=self.object), auto_id='id_fs_distri_no_%s')
return context return context
def handle_submit_edit_post(self, request, **kwargs): def handle_submit_edit_post(self, request, **kwargs):
@ -438,18 +443,76 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
return self.render_to_response(context) return self.render_to_response(context)
def handle_submit_edit_params_post(self, request, **kwargs): def handle_submit_edit_params_post(self, request, **kwargs):
ParameterFormset = forms.formset_factory(EditComponentParameterForm, extra=1, max_num=100)
fs = ParameterFormset(initial=self.prepare_initial_param_formset_data(), data=request.POST)
errors_set = False
if fs.is_valid():
# Go through all the parameter forms:
for form in fs:
if not form.has_changed():
continue
# Form has changed. Process the new value
try:
parameter_to_change = ComponentParameter.objects.get(component=self.object,
parameter_type__parameter_name=form.initial['parameter_type'])
parameter_to_change.parameter_type = form.cleaned_data['parameter_type_object']
parameter_to_change.value = 0
parameter_to_change.text_value = None
except:
try:
parameter_to_change = ComponentParameter.objects.create(component=self.object,
parameter_type=form.cleaned_data['parameter_type_object'])
except:
form.add_error('parameter_type', 'Parameter could not be saved. Unique?')
errors_set = True
break
parameter_to_change.value = 0
parameter_to_change.text_value = None
if parameter_to_change.parameter_type.parameter_type == 'F':
parameter_to_change.text_value = form.cleaned_data['processed_value']
parameter_to_change.value = 0
else:
parameter_to_change.value = form.cleaned_data['processed_value']
try:
parameter_to_change.save()
except:
form.add_error('parameter_type', 'Parameter could not be saved. Unique?')
errors_set = True
context = self.get_context_data() context = self.get_context_data()
if not fs.is_valid() or errors_set:
context['param_formset'] = fs
return self.render_to_response(context) return self.render_to_response(context)
def handle_submit_edit_distri_nums_post(self, request, **kwargs):
DistriNumFormSet = forms.modelformset_factory(DistributorNum, form=DistributorNumberForm, extra=2, formset=DistributorNumberFormSet)
fs = DistriNumFormSet(queryset=DistributorNum.objects.filter(component=self.object), data=request.POST, auto_id='id_fs_distri_no_%s')
if fs.is_valid():
print('Valid')
fs.save(self.object)
else:
print('Invalid')
context = self.get_context_data()
if not fs.is_valid():
context['distri_num_formset'] = fs
return self.render_to_response(context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
if 'submit-edit-comp' in request.POST: if 'submit-edit-comp' in request.POST:
return self.handle_submit_edit_post(request, **kwargs) return self.handle_submit_edit_post(request, **kwargs)
elif 'submit-edit-params' in request.POST: elif 'submit-edit-params' in request.POST:
return self.handle_submit_edit_params_post(request, **kwargs) return self.handle_submit_edit_params_post(request, **kwargs)
elif 'submit-edit-distri-nums' in request.POST:
return self.handle_submit_edit_distri_nums_post(request, **kwargs)
return super().post(request, *args, **kwargs) return super().post(request, *args, **kwargs)

View File

@ -24,7 +24,7 @@
<button class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#comp-edit-modal"><i class="bi bi-pencil-square"></i> Edit Component</button> <button class="btn btn-primary mb-2" data-bs-toggle="modal" data-bs-target="#comp-edit-modal"><i class="bi bi-pencil-square"></i> Edit Component</button>
</div> </div>
</div> </div>
<div class="col"> <div class="col m-1">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
@ -65,17 +65,36 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<h2>Description</h2>
{% if component.description %}
{{component.description|linebreaks}}
{% else %}
<div class="alert alert-secondary" role="alert">
No description available
</div>
{% endif %}
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h2>Parameters</h2> <h2>Description</h2>
{% if component.description %}
{{component.description|linebreaks}}
{% else %}
<div class="alert alert-secondary" role="alert">
No description available
</div>
{% endif %}
</div>
<div class="col-4">
{% if component.pref_distri %}
<h4>Preferred Distributor</h4>
<div class="d-flex align-items-center">
{% if component.pref_distri.image %}
<div class="flex-shrink-0">
<img src="{{component.pref_distri.image.url}}" alt="{{component.pref_distri.name}}" class="component-img-big">
</div>
<div class="flex-grow-1 ms-2">
<h6>{{component.pref_distri.name}}</h6>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
<div class="row">
<div class="col">
<h3>Parameters</h3>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
<table class="table"> <table class="table">
@ -87,35 +106,81 @@
<tbody> <tbody>
{% for f in param_formset %} {% for f in param_formset %}
<tr> <tr>
<td><input type="text" class="form-control" name="{{f.parameter_type.name}}" value="{{f.parameter_type.value}}"></td> <td><input type="text" class="form-control{% if f.parameter_type.errors %} is-invalid{% endif %}" name="{{f.parameter_type.html_name}}" value="{{f.parameter_type.value}}"></td>
<td><input type="text" class="form-control" name="{{f.value.name}}" value="{{f.value.value}}"></td> <td><input type="text" class="form-control{% if f.value.errors %} is-invalid{% endif %}" name="{{f.value.html_name}}" value="{{f.value.value}}"></td>
<td>{{f.parameter_type_object.unit|default_if_none:""}}</td> <td>{{f.parameter_type_object.unit|default_if_none:"-"}}</td>
</tr> </tr>
{% if f.errors %}
<tr class="text-danger">
<td>
{% if f.parameter_type.errors %}
{{f.parameter_type.errors}}
{% endif %}
</td>
<td>
{% if f.value.errors %}
{{f.value.errors}}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{{param_formset.management_form}}
<input type="submit" class="btn btn-primary" name="submit-edit-params" value="Save Parameters"> <input type="submit" class="btn btn-primary" name="submit-edit-params" value="Save Parameters">
</form> </form>
</div> </div>
<div class="col"> <div class="col">
<h2>Stocks</h2> <h3>Distributor Part Numbers</h3>
<table class="table"> <form method="post">
<thead> {% csrf_token %}
<th scope="col">Storage</th> <table class="table">
<th scope="col">Amount</th> <thead>
</thead> <th scope="col">Distributor</th>
<tbody> <th scope="col">Part Number</th>
{% for stock in stocks %} </thead>
<tr> <tbody>
<td><a class="text-decoration-none text-primary" href="{% url 'parts-stocks-detail' uuid=stock.storage.id %}">{{stock.storage.get_full_path}}</a></td> {% for form in distri_num_formset %}
<td>{{stock.amount}}</td> <tr>
<tr> <td>
{% endfor %} {% if form.instance.distributor %}
</tbody> {{form.instance.distributor.name}}
</table> {% else %}
<input type="text" name="__unused_search" id="{{form.distributor.id_for_label}}-search">
{% endif %}
</td>
<input type="hidden" name="{{form.distributor.html_name}}" id="{{form.distributor.id_for_label}}" value="{{form.distributor.value|default_if_none:""}}">
<input type="hidden" name="{{form.id.html_name}}" value="{{form.id.value|default_if_none:""}}">
<td>
<input class="form-control" type="text" name="{{form.distributor_part_number.html_name}}" id="{{form.distributor_part_number.id_for_label}}" value="{{form.distributor_part_number.value|default_if_none:""}}">
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{distri_num_formset.management_form}}
<input type="submit" class="btn btn-secondary" name="submit-edit-distri-nums" value="Save">
</form>
</div> </div>
</div> </div>
<div class="row mt-2">
<table class="table">
<thead>
<th scope="col">Storage</th>
<th scope="col">Amount</th>
</thead>
<tbody>
{% for stock in stocks %}
<tr>
<td><a class="text-decoration-none text-primary" href="{% url 'parts-stocks-detail' uuid=stock.storage.id %}">{{stock.storage.get_full_path}}</a></td>
<td>{{stock.amount}}</td>
<tr>
{% endfor %}
</tbody>
</table>
</div>
</div> </div>
</div> </div>
</div> </div>