Implement package parameters

This commit is contained in:
Mario Hüttel 2024-11-24 01:39:03 +01:00
parent 26b001d983
commit c19f4a8159
6 changed files with 150 additions and 5 deletions

View File

@ -252,15 +252,19 @@ class DistributorNumberDeleteForm(forms.Form):
class ComponentParameterDeleteForm(forms.Form):
param_num = forms.UUIDField(required=True)
model = parts_models.ComponentParameter
def clean_param_num(self):
my_uuid = self.cleaned_data['param_num']
try:
param = parts_models.ComponentParameter.objects.get(id=my_uuid)
param = self.model.objects.get(id=my_uuid)
except:
raise ValidationError('Parameter Number Invalid')
return param
class PackageParameterDeleteForm(ComponentParameterDeleteForm):
model = parts_models.PackageParameter
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)
@ -309,6 +313,7 @@ class ComponentParameterSearchForm(forms.Form):
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)
model = parts_models.ComponentParameter
def clean(self):
data = super().clean()
@ -338,7 +343,20 @@ class ComponentParameterCreateForm(forms.Form):
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)
self.model.objects.create(parameter_type=param_type, component=component, value=value, text_value=text_value)
class PackageParameterCreateForm(ComponentParameterCreateForm):
model = parts_models.PackageParameter
def save(self, package):
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']
self.model.objects.create(parameter_type=param_type, package=package, value=value, text_value=text_value)
class QrSearchForm(forms.Form):
my_qr_validator = QrCodeValidator()

View File

@ -0,0 +1,37 @@
from django.core.management.base import BaseCommand, CommandParser
from django.contrib.auth import get_user_model
from parts.models import Component, ComponentParameter, ComponentParameterType, PackageParameter, Package
class Command(BaseCommand):
help = "Remove component parameters, that are also set on the package with the same value"
def add_arguments(self, parser: CommandParser):
parser.add_argument('--dry-run',
help='Do not perform parameter deletion. Print only',
action='store_true')
def handle(self, *args, **options):
# Get all components with set packages. Ignore the ones without packages
all_comps = Component.objects.exclude(package__isnull=True)
for component in all_comps:
package_parameters = PackageParameter.objects.filter(package=component.package)
component_parameters = ComponentParameter.objects.filter(component=component)
package_param_ids = package_parameters.values_list('parameter_type_id', flat=True)
component_param_ids = component_parameters.values_list('parameter_type_id', flat=True)
self.stdout.write(f'Comp: {str(component)} Found {len(component_param_ids)} different parameters')
self.stdout.write(f'\tPackage: {str(component.package)} Found {len(package_param_ids)} different parameters')
commontypes = ctypes = ComponentParameterType.objects.filter(id__in=component_param_ids).filter(id__in=package_param_ids)
self.stdout.write(f'\tCommon parameter count: {len(commontypes)}')
# Check if values are the same when rendered as a string. This avoids float comparison problems
for common_type in commontypes:
s1 = package_parameters.filter(parameter_type=common_type).first().resolved_value_as_string()
comp_param = component_parameters.filter(parameter_type=common_type).first()
s2 = comp_param.resolved_value_as_string()
if s1 == s2:
self.stdout.write(f'\tParameter {common_type.parameter_name} is the same value for component and package: {s1}. Removing from component')
if not options['dry_run']:
comp_param.delete()

View File

@ -8,7 +8,7 @@ from django.db.models import Q
from django.forms import formset_factory
from django.db import IntegrityError
from django.db.models import ProtectedError
from ..models import Stock, Component, ComponentParameter, DistributorNum
from ..models import Stock, Component, ComponentParameter, DistributorNum, PackageParameter
from ..forms import *
from .component_import import import_components_from_csv
from .generic_views import BaseTemplateMixin
@ -174,6 +174,8 @@ class ComponentDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
'distributor__name')
context['parameters'] = ComponentParameter.objects.filter(component=self.object).order_by(
'parameter_type__parameter_name')
context['package_parameters'] = PackageParameter.objects.filter(package=self.object.package).order_by(
'parameter_type__parameter_name')
return context

View File

@ -5,7 +5,7 @@ from django.core.paginator import Paginator
from django.db.models import ProtectedError
from django.db.models import Q
from ..forms import *
from ..models import Package
from ..models import Package, PackageParameter
from .generic_views import BaseTemplateMixin
class PackageView(LoginRequiredMixin, BaseTemplateMixin, TemplateView):
@ -82,6 +82,9 @@ class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
context = super().get_context_data(**kwargs)
context['package'] = self.object
context['edit_form'] = PackageForm(instance=self.object)
context['new_param_form'] = PackageParameterCreateForm()
context['parameters'] = PackageParameter.objects.filter(package=self.object).order_by(
'parameter_type__parameter_name')
return context
@ -116,6 +119,27 @@ class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
if not edit_form.is_valid():
context['edit_form'] = edit_form
return self.render_to_response(context)
def handle_submit_delete_param_post(self, request, **kwargs):
form = PackageParameterDeleteForm(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 = PackageParameterCreateForm(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()
@ -124,5 +148,9 @@ class PackageDetailView(LoginRequiredMixin, BaseTemplateMixin, DetailView):
return self.handle_delete_package(request)
elif 'submit-pkg-edit' in request.POST:
return self.edit_package(request)
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)
return super().post(request, *args, **kwargs)

View File

@ -119,6 +119,19 @@
<th scope="col"></th>
</thead>
<tbody>
{% for param in package_parameters %}
<tr>
<td>
<h6 {% if param.parameter_type.parameter_description %} class="accordion-header" data-bs-toggle="collapse" data-bs-target="#collapse-pkg-parameter-desc-{{forloop.counter}}"{% endif %}>
{{param.parameter_type.parameter_name}}
</h6>
</td>
<td>
{{param.resolved_value_as_string}}
</td>
<td><span class="text-info">from Package</span></td>
</tr>
{% endfor %}
{% for param in parameters %}
<tr>
<td>
@ -148,6 +161,13 @@
</div>
{% endif %}
{% endfor %}
{% for param in package_parameters %}
{% if param.parameter_type.parameter_description %}
<div class="collapse accordion-collapse" id="collapse-pkg-parameter-desc-{{forloop.counter}}" data-bs-parent="#accordion-param-desc">
{{param.parameter_type.parameter_description}}
</div>
{% endif %}
{% endfor %}
</div>
</div>
<div class="col">

View File

@ -26,6 +26,46 @@
<input type="submit" class="btn btn-primary" value="Save" name="submit-pkg-edit">
</form>
</div>
<div class="col-md-3">
<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 align-middle mb-3">
<thead>
<th scope="col">Parameter</th>
<th scope="col">Value</th>
<th scope="col"></th>
</thead>
<tbody>
{% for param in parameters %}
<tr>
<td>
<h6 {% if param.parameter_type.parameter_description %} class="accordion-header" data-bs-toggle="collapse" data-bs-target="#collapse-parameter-desc-{{forloop.counter}}"{% endif %}>
{{param.parameter_type.parameter_name}}
</h6>
</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 class="accordion" id="accordion-param-desc">
{% for param in parameters %}
{% if param.parameter_type.parameter_description %}
<div class="collapse accordion-collapse" id="collapse-parameter-desc-{{forloop.counter}}" data-bs-parent="#accordion-param-desc">
{{param.parameter_type.parameter_description}}
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
@ -80,7 +120,7 @@
</div>
</div>
</div>
{% include 'parts/modals/new-component-parameter-modal.html' with component_name=object.name form=new_param_form %}
{% endblock content %}