mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 21:25:42 +00:00 
			
		
		
		
	Refactor SupplierPartEdit and SupplierPartDelete forms
This commit is contained in:
		| @@ -6,13 +6,12 @@ Django Forms for interacting with Company app | ||||
| from __future__ import unicode_literals | ||||
|  | ||||
| from InvenTree.forms import HelperForm | ||||
| from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField | ||||
| from InvenTree.fields import RoundingDecimalFormField | ||||
|  | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| import django.forms | ||||
|  | ||||
| from .models import Company | ||||
| from .models import SupplierPart | ||||
| from .models import SupplierPriceBreak | ||||
|  | ||||
|  | ||||
| @@ -34,67 +33,6 @@ class CompanyImageDownloadForm(HelperForm): | ||||
|         ] | ||||
|  | ||||
|  | ||||
| class EditSupplierPartForm(HelperForm): | ||||
|     """ Form for editing a SupplierPart object """ | ||||
|  | ||||
|     field_prefix = { | ||||
|         'link': 'fa-link', | ||||
|         'SKU': 'fa-hashtag', | ||||
|         'note': 'fa-pencil-alt', | ||||
|     } | ||||
|  | ||||
|     single_pricing = InvenTreeMoneyField( | ||||
|         label=_('Single Price'), | ||||
|         help_text=_('Single quantity price'), | ||||
|         decimal_places=4, | ||||
|         max_digits=19, | ||||
|         required=False, | ||||
|     ) | ||||
|  | ||||
|     manufacturer = django.forms.ChoiceField( | ||||
|         required=False, | ||||
|         help_text=_('Select manufacturer'), | ||||
|         choices=[], | ||||
|     ) | ||||
|  | ||||
|     MPN = django.forms.CharField( | ||||
|         required=False, | ||||
|         help_text=_('Manufacturer Part Number'), | ||||
|         max_length=100, | ||||
|         label=_('MPN'), | ||||
|     ) | ||||
|  | ||||
|     class Meta: | ||||
|         model = SupplierPart | ||||
|         fields = [ | ||||
|             'part', | ||||
|             'supplier', | ||||
|             'SKU', | ||||
|             'manufacturer', | ||||
|             'MPN', | ||||
|             'description', | ||||
|             'link', | ||||
|             'note', | ||||
|             'single_pricing', | ||||
|             # 'base_cost', | ||||
|             # 'multiple', | ||||
|             'packaging', | ||||
|         ] | ||||
|  | ||||
|     def get_manufacturer_choices(self): | ||||
|         """ Returns tuples for all manufacturers """ | ||||
|         empty_choice = [('', '----------')] | ||||
|  | ||||
|         manufacturers = [(manufacturer.id, manufacturer.name) for manufacturer in Company.objects.filter(is_manufacturer=True)] | ||||
|  | ||||
|         return empty_choice + manufacturers | ||||
|  | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         super().__init__(*args, **kwargs) | ||||
|  | ||||
|         self.fields['manufacturer'].choices = self.get_manufacturer_choices() | ||||
|  | ||||
|  | ||||
| class EditPriceBreakForm(HelperForm): | ||||
|     """ Form for creating / editing a supplier price break """ | ||||
|  | ||||
|   | ||||
| @@ -9,9 +9,7 @@ import os | ||||
|  | ||||
| from django.utils.translation import ugettext_lazy as _ | ||||
| from django.core.validators import MinValueValidator | ||||
| from django.core.exceptions import ValidationError | ||||
| from django.db import models | ||||
| from django.db.utils import IntegrityError | ||||
| from django.db.models import Sum, Q, UniqueConstraint | ||||
|  | ||||
| from django.apps import apps | ||||
|   | ||||
| @@ -378,22 +378,27 @@ | ||||
|     {% endif %} | ||||
|  | ||||
|     $("#multi-part-delete").click(function() { | ||||
|         var selections = $("#part-table").bootstrapTable("getSelections"); | ||||
|         var selections = $("#supplier-part-table").bootstrapTable("getSelections"); | ||||
|  | ||||
|         var parts = []; | ||||
|         var requests = []; | ||||
|  | ||||
|         selections.forEach(function(item) { | ||||
|             parts.push(item.pk); | ||||
|         showQuestionDialog( | ||||
|             '{% trans "Delete Supplier Parts?" %}', | ||||
|             '{% trans "All selected supplier parts will be deleted" %}', | ||||
|             { | ||||
|                 accept: function() { | ||||
|                     selections.forEach(function(part) { | ||||
|                         var url = `/api/company/part/${part.pk}/`; | ||||
|              | ||||
|                         requests.push(inventreeDelete(url)); | ||||
|                     }); | ||||
|              | ||||
|         var url = "{% url 'supplier-part-delete' %}" | ||||
|  | ||||
|         launchModalForm(url, { | ||||
|             data: { | ||||
|                 parts: parts, | ||||
|             }, | ||||
|             reload: true, | ||||
|                     $.when.apply($, requests).then(function() { | ||||
|                         $('#supplier-part-table').bootstrapTable('refresh'); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     }); | ||||
|  | ||||
|     $("#multi-part-order").click(function() { | ||||
|   | ||||
| @@ -194,18 +194,25 @@ $("#supplier-part-delete").click(function() { | ||||
|  | ||||
|     var selections = $("#supplier-table").bootstrapTable("getSelections"); | ||||
|  | ||||
|     var parts = []; | ||||
|     var requests = []; | ||||
|  | ||||
|     selections.forEach(function(item) { | ||||
|         parts.push(item.pk); | ||||
|     showQuestionDialog( | ||||
|         '{% trans "Delete Supplier Parts?" %}', | ||||
|         '{% trans "All selected supplier parts will be deleted" %}', | ||||
|         { | ||||
|             accept: function() { | ||||
|                 selections.forEach(function(part) { | ||||
|                     var url = `/api/company/part/${part.pk}/`; | ||||
|          | ||||
|                     requests.push(inventreeDelete(url)); | ||||
|                 }); | ||||
|          | ||||
|     launchModalForm("{% url 'supplier-part-delete' %}", { | ||||
|         data: { | ||||
|             parts: parts, | ||||
|         }, | ||||
|         reload: true, | ||||
|                 $.when.apply($, requests).then(function() { | ||||
|                     reloadSupplierPartTable(); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|     ); | ||||
| }); | ||||
|  | ||||
| $("#multi-parameter-delete").click(function() { | ||||
|   | ||||
| @@ -327,21 +327,21 @@ $('#order-part, #order-part2').click(function() { | ||||
| }); | ||||
|  | ||||
| $('#edit-part').click(function () { | ||||
|     launchModalForm( | ||||
|                     "{% url 'supplier-part-edit' part.id %}", | ||||
|                     { | ||||
|                         reload: true | ||||
|  | ||||
|     editSupplierPart({{ part.pk }}, { | ||||
|         onSuccess: function() { | ||||
|             location.reload(); | ||||
|         } | ||||
|     ); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| $('#delete-part').click(function() { | ||||
|     launchModalForm( | ||||
|         "{% url 'supplier-part-delete' %}?part={{ part.id }}", | ||||
|         { | ||||
|             redirect: "{% url 'company-detail' part.supplier.id %}" | ||||
|  | ||||
|     deleteSupplierPart({{ part.pk }}, { | ||||
|         onSuccess: function() { | ||||
|             window.location.href = "{% url 'company-detail' part.supplier.id %}"; | ||||
|         } | ||||
|     ); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| attachNavCallbacks({ | ||||
|   | ||||
| @@ -1,17 +0,0 @@ | ||||
| {% extends "modal_form.html" %} | ||||
|  | ||||
| {% load i18n %} | ||||
|  | ||||
| {% block pre_form_content %} | ||||
| {{ block.super }} | ||||
|  | ||||
| {% if part %} | ||||
| <div class='alert alert-block alert-info'> | ||||
|     {% include "hover_image.html" with image=part.image %} | ||||
|     {{ part.full_name}} | ||||
|     <br> | ||||
|     <i>{{ part.description }}</i> | ||||
| </div> | ||||
| {% endif %} | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -1,31 +0,0 @@ | ||||
| {% extends "modal_delete_form.html" %} | ||||
| {% load i18n %} | ||||
|  | ||||
| {% block pre_form_content %} | ||||
| {% trans "Are you sure you want to delete the following Supplier Parts?" %} | ||||
|  | ||||
| <hr> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block form_data %} | ||||
| <table class='table table-striped table-condensed'> | ||||
| {% for part in parts %} | ||||
| <tr> | ||||
|     <input type='hidden' name='supplier-part-{{ part.id}}' value='supplier-part-{{ part.id }}'/> | ||||
|  | ||||
|     <td> | ||||
|         {% include "hover_image.html" with image=part.part.image %} | ||||
|         {{ part.part.full_name }} | ||||
|     </td> | ||||
|     <td> | ||||
|         {% include "hover_image.html" with image=part.supplier.image %} | ||||
|         {{ part.supplier.name }} | ||||
|     </td> | ||||
|     <td> | ||||
|         {{ part.SKU }} | ||||
|     </td> | ||||
| </tr> | ||||
| {% endfor %} | ||||
| </table> | ||||
|  | ||||
| {% endblock %} | ||||
| @@ -10,9 +10,6 @@ from django.urls import reverse | ||||
| from django.contrib.auth import get_user_model | ||||
| from django.contrib.auth.models import Group | ||||
|  | ||||
| from .models import ManufacturerPart | ||||
| from .models import SupplierPart | ||||
|  | ||||
|  | ||||
| class CompanyViewTestBase(TestCase): | ||||
|  | ||||
|   | ||||
| @@ -35,14 +35,6 @@ manufacturer_part_urls = [ | ||||
|     ])), | ||||
| ] | ||||
|  | ||||
| supplier_part_detail_urls = [ | ||||
|     url(r'^edit/?', views.SupplierPartEdit.as_view(), name='supplier-part-edit'), | ||||
|  | ||||
| supplier_part_urls = [ | ||||
|     url('^.*$', views.SupplierPartDetail.as_view(template_name='company/supplier_part.html'), name='supplier-part-detail'), | ||||
| ] | ||||
|  | ||||
| supplier_part_urls = [ | ||||
|     url(r'delete/', views.SupplierPartDelete.as_view(), name='supplier-part-delete'), | ||||
|  | ||||
|     url(r'^(?P<pk>\d+)/', include(supplier_part_detail_urls)), | ||||
| ] | ||||
|   | ||||
| @@ -10,31 +10,22 @@ from django.utils.translation import ugettext_lazy as _ | ||||
| from django.views.generic import DetailView, ListView | ||||
|  | ||||
| from django.urls import reverse | ||||
| from django.forms import HiddenInput | ||||
| from django.core.files.base import ContentFile | ||||
|  | ||||
| from moneyed import CURRENCIES | ||||
|  | ||||
| from PIL import Image | ||||
| import requests | ||||
| import io | ||||
|  | ||||
| from InvenTree.views import AjaxCreateView, AjaxUpdateView, AjaxDeleteView | ||||
| from InvenTree.helpers import str2bool | ||||
| from InvenTree.views import AjaxUpdateView | ||||
| from InvenTree.views import InvenTreeRoleMixin | ||||
|  | ||||
| from .models import Company | ||||
| from .models import ManufacturerPart | ||||
| from .models import SupplierPart | ||||
|  | ||||
| from part.models import Part | ||||
|  | ||||
| from .forms import EditSupplierPartForm | ||||
| from .forms import CompanyImageDownloadForm | ||||
|  | ||||
| import common.models | ||||
| import common.settings | ||||
|  | ||||
|  | ||||
| class CompanyIndex(InvenTreeRoleMixin, ListView): | ||||
|     """ View for displaying list of companies | ||||
| @@ -231,134 +222,3 @@ class SupplierPartDetail(DetailView): | ||||
|         ctx = super().get_context_data(**kwargs) | ||||
|  | ||||
|         return ctx | ||||
|  | ||||
|  | ||||
| class SupplierPartEdit(AjaxUpdateView): | ||||
|     """ Update view for editing SupplierPart """ | ||||
|  | ||||
|     model = SupplierPart | ||||
|     context_object_name = 'part' | ||||
|     form_class = EditSupplierPartForm | ||||
|     ajax_template_name = 'modal_form.html' | ||||
|     ajax_form_title = _('Edit Supplier Part') | ||||
|  | ||||
|     def save(self, supplier_part, form, **kwargs): | ||||
|         """ Process ManufacturerPart data """ | ||||
|  | ||||
|         manufacturer = form.cleaned_data.get('manufacturer', None) | ||||
|         MPN = form.cleaned_data.get('MPN', None) | ||||
|         kwargs = {'manufacturer': manufacturer, | ||||
|                   'MPN': MPN, | ||||
|                   } | ||||
|         supplier_part.save(**kwargs) | ||||
|  | ||||
|     def get_form(self): | ||||
|         form = super().get_form() | ||||
|  | ||||
|         supplier_part = self.get_object() | ||||
|  | ||||
|         # Hide Manufacturer fields | ||||
|         form.fields['manufacturer'].widget = HiddenInput() | ||||
|         form.fields['MPN'].widget = HiddenInput() | ||||
|  | ||||
|         # It appears that hiding a MoneyField fails validation | ||||
|         # Therefore the idea to set the value before hiding | ||||
|         if form.is_valid(): | ||||
|             form.cleaned_data['single_pricing'] = supplier_part.unit_pricing | ||||
|         # Hide the single-pricing field (only for creating a new SupplierPart!) | ||||
|         form.fields['single_pricing'].widget = HiddenInput() | ||||
|  | ||||
|         return form | ||||
|  | ||||
|     def get_initial(self): | ||||
|         """ Fetch data from ManufacturerPart """ | ||||
|  | ||||
|         initials = super(SupplierPartEdit, self).get_initial().copy() | ||||
|  | ||||
|         supplier_part = self.get_object() | ||||
|  | ||||
|         if supplier_part.manufacturer_part: | ||||
|             if supplier_part.manufacturer_part.manufacturer: | ||||
|                 initials['manufacturer'] = supplier_part.manufacturer_part.manufacturer.id | ||||
|             initials['MPN'] = supplier_part.manufacturer_part.MPN | ||||
|  | ||||
|         return initials | ||||
|  | ||||
|  | ||||
| class SupplierPartDelete(AjaxDeleteView): | ||||
|     """ Delete view for removing a SupplierPart. | ||||
|  | ||||
|     SupplierParts can be deleted using a variety of 'selectors'. | ||||
|  | ||||
|     - ?part=<pk> -> Delete a single SupplierPart object | ||||
|     - ?parts=[] -> Delete a list of SupplierPart objects | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     success_url = '/supplier/' | ||||
|     ajax_template_name = 'company/supplier_part_delete.html' | ||||
|     ajax_form_title = _('Delete Supplier Part') | ||||
|  | ||||
|     role_required = 'purchase_order.delete' | ||||
|  | ||||
|     parts = [] | ||||
|  | ||||
|     def get_context_data(self): | ||||
|         ctx = {} | ||||
|  | ||||
|         ctx['parts'] = self.parts | ||||
|  | ||||
|         return ctx | ||||
|  | ||||
|     def get_parts(self): | ||||
|         """ Determine which SupplierPart object(s) the user wishes to delete. | ||||
|         """ | ||||
|  | ||||
|         self.parts = [] | ||||
|  | ||||
|         # User passes a single SupplierPart ID | ||||
|         if 'part' in self.request.GET: | ||||
|             try: | ||||
|                 self.parts.append(SupplierPart.objects.get(pk=self.request.GET.get('part'))) | ||||
|             except (ValueError, SupplierPart.DoesNotExist): | ||||
|                 pass | ||||
|  | ||||
|         elif 'parts[]' in self.request.GET: | ||||
|  | ||||
|             part_id_list = self.request.GET.getlist('parts[]') | ||||
|  | ||||
|             self.parts = SupplierPart.objects.filter(id__in=part_id_list) | ||||
|  | ||||
|     def get(self, request, *args, **kwargs): | ||||
|         self.request = request | ||||
|         self.get_parts() | ||||
|  | ||||
|         return self.renderJsonResponse(request, form=self.get_form()) | ||||
|  | ||||
|     def post(self, request, *args, **kwargs): | ||||
|         """ Handle the POST action for deleting supplier parts. | ||||
|         """ | ||||
|  | ||||
|         self.request = request | ||||
|         self.parts = [] | ||||
|  | ||||
|         for item in self.request.POST: | ||||
|             if item.startswith('supplier-part-'): | ||||
|                 pk = item.replace('supplier-part-', '') | ||||
|  | ||||
|                 try: | ||||
|                     self.parts.append(SupplierPart.objects.get(pk=pk)) | ||||
|                 except (ValueError, SupplierPart.DoesNotExist): | ||||
|                     pass | ||||
|  | ||||
|         confirm = str2bool(self.request.POST.get('confirm_delete', False)) | ||||
|  | ||||
|         data = { | ||||
|             'form_valid': confirm, | ||||
|         } | ||||
|  | ||||
|         if confirm: | ||||
|             for part in self.parts: | ||||
|                 part.delete() | ||||
|  | ||||
|         return self.renderJsonResponse(self.request, data=data, form=self.get_form()) | ||||
|   | ||||
| @@ -817,18 +817,25 @@ | ||||
|  | ||||
|         var selections = $("#supplier-part-table").bootstrapTable("getSelections"); | ||||
|  | ||||
|         var parts = []; | ||||
|         var requests = []; | ||||
|  | ||||
|         selections.forEach(function(item) { | ||||
|             parts.push(item.pk); | ||||
|         showQuestionDialog( | ||||
|             '{% trans "Delete Supplier Parts?" %}', | ||||
|             '{% trans "All selected supplier parts will be deleted" %}', | ||||
|             { | ||||
|                 accept: function() { | ||||
|                     selections.forEach(function(part) { | ||||
|                         var url = `/api/company/part/${part.pk}/`; | ||||
|              | ||||
|                         requests.push(inventreeDelete(url)); | ||||
|                     }); | ||||
|              | ||||
|         launchModalForm("{% url 'supplier-part-delete' %}", { | ||||
|             data: { | ||||
|                 parts: parts, | ||||
|             }, | ||||
|             reload: true, | ||||
|                     $.when.apply($, requests).then(function() { | ||||
|                         reloadSupplierPartTable(); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     }); | ||||
|  | ||||
|     loadSupplierPartTable( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user