From 0b1f22c7fde20c38bd17a790089fba480157ba9c Mon Sep 17 00:00:00 2001
From: eeintech <eeintech@eeinte.ch>
Date: Tue, 30 Mar 2021 18:08:33 -0400
Subject: [PATCH] Almost there, needs some interface testing and tweaking

---
 InvenTree/company/api.py                      |  6 +++
 InvenTree/company/forms.py                    | 29 +++++++++++++-
 InvenTree/company/models.py                   | 29 +++++++++++---
 .../company/manufacturer_part_suppliers.html  |  9 +----
 InvenTree/company/views.py                    | 40 +++++++++++++++++++
 InvenTree/stock/api.py                        |  4 +-
 InvenTree/stock/serializers.py                |  2 +-
 7 files changed, 103 insertions(+), 16 deletions(-)

diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py
index eb0d7fc4e6..be44c7cf46 100644
--- a/InvenTree/company/api.py
+++ b/InvenTree/company/api.py
@@ -235,6 +235,12 @@ class SupplierPartList(generics.ListCreateAPIView):
         if part is not None:
             queryset = queryset.filter(part=part)
 
+        # Filter by manufacturer part?
+        manufacturer_part = params.get('manufacturer_part', None)
+
+        if manufacturer_part is not None:
+            queryset = queryset.filter(manufacturer_part=manufacturer_part)
+
         # Filter by 'active' status of the part?
         active = params.get('active', None)
 
diff --git a/InvenTree/company/forms.py b/InvenTree/company/forms.py
index ac10cc291a..bc3e7ec353 100644
--- a/InvenTree/company/forms.py
+++ b/InvenTree/company/forms.py
@@ -122,13 +122,27 @@ class EditSupplierPartForm(HelperForm):
         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_part',
+            'manufacturer',
+            'MPN',
             'description',
             'link',
             'note',
@@ -138,6 +152,19 @@ class EditSupplierPartForm(HelperForm):
             'packaging',
         ]
 
+    def get_manufacturer_choices(self):
+        """ Returns tuples for all manufacturers """
+        empty_choice = [('', '----------')]
+
+        manufacturers = [(manufacturer.id, manufacturer.name) for manufacturer in Company.objects.all()]
+        
+        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 """
diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py
index b904912cb2..2c6a6d650c 100644
--- a/InvenTree/company/models.py
+++ b/InvenTree/company/models.py
@@ -217,7 +217,7 @@ class Company(models.Model):
     def stock_items(self):
         """ Return a list of all stock items supplied or manufactured by this company """
         stock = apps.get_model('stock', 'StockItem')
-        return stock.objects.filter(Q(supplier_part__supplier=self.id) | Q(supplier_part__manufacturer=self.id)).all()
+        return stock.objects.filter(Q(supplier_part__supplier=self.id) | Q(supplier_part__manufacturer_part__manufacturer=self.id)).all()
 
     @property
     def stock_count(self):
@@ -335,6 +335,25 @@ class ManufacturerPart(models.Model):
         help_text=_('Manufacturer part description')
     )
 
+    @classmethod
+    def create(cls, part, manufacturer, mpn, link, description):
+        """ Check if ManufacturerPart instance does not already exist
+            then create it
+        """
+
+        manufacturer_part = None
+
+        try:
+            manufacturer_part = ManufacturerPart.objects.get(part=part, manufacturer=manufacturer, MPN=mpn)
+        except ManufacturerPart.DoesNotExist:
+            pass
+
+        if not manufacturer_part:
+            manufacturer_part = ManufacturerPart(part=part, manufacturer=manufacturer, MPN=mpn, description=description, link=link)
+            manufacturer_part.save()
+            
+        return manufacturer_part
+
     def __str__(self):
         s = ''
 
@@ -440,10 +459,10 @@ class SupplierPart(models.Model):
 
         items = []
 
-        if self.manufacturer:
-            items.append(self.manufacturer.name)
-        if self.MPN:
-            items.append(self.MPN)
+        if self.manufacturer_part.manufacturer:
+            items.append(self.manufacturer_part.manufacturer.name)
+        if self.manufacturer_part.MPN:
+            items.append(self.manufacturer_part.MPN)
 
         return ' | '.join(items)
 
diff --git a/InvenTree/company/templates/company/manufacturer_part_suppliers.html b/InvenTree/company/templates/company/manufacturer_part_suppliers.html
index 60f01f7bf2..0d39516a7b 100644
--- a/InvenTree/company/templates/company/manufacturer_part_suppliers.html
+++ b/InvenTree/company/templates/company/manufacturer_part_suppliers.html
@@ -39,7 +39,7 @@ $('#supplier-create').click(function () {
         {
             reload: true,
             data: {
-                part: {{ part.id }}
+                manufacturer_part: {{ part.id }}
             },
             secondary: [
                 {
@@ -48,12 +48,6 @@ $('#supplier-create').click(function () {
                     title: '{% trans "Create new supplier" %}',
                     url: "{% url 'supplier-create' %}"
                 },
-                {
-                    field: 'manufacturer',
-                    label: '{% trans "New Manufacturer" %}',
-                    title: '{% trans "Create new manufacturer" %}',
-                    url: "{% url 'manufacturer-create' %}",
-                }
             ]
         });
 });
@@ -82,6 +76,7 @@ loadSupplierPartTable(
     {
         params: {
             part: {{ part.part.id }},
+            manufacturer_part: {{ part.id }},
             part_detail: true,
             supplier_detail: true,
             manufacturer_detail: true,
diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py
index dbcc5948da..81bef9c7d0 100644
--- a/InvenTree/company/views.py
+++ b/InvenTree/company/views.py
@@ -585,9 +585,30 @@ class SupplierPartCreate(AjaxCreateView):
         If single_pricing is defined, add a price break for quantity=1
         """
 
+        # Process manufacturer data
+        part = form.cleaned_data.get('part', None)
+        print(f'{part=}')
+        manufacturer_id = form.cleaned_data.get('manufacturer', None)
+        
+        manufacturer_part = None
+        if manufacturer_id:
+            manufacturer = Company.objects.get(pk=manufacturer_id)
+            MPN = form.cleaned_data.get('MPN', None)
+            description = form.cleaned_data.get('description', None)
+            link = form.cleaned_data.get('link', None)
+
+            manufacturer_part = ManufacturerPart.create(part=part, manufacturer=manufacturer, mpn=MPN, description=description, link=link)
+
         # Save the supplier part object
         supplier_part = super().save(form)
 
+        print(f'{manufacturer_part=}')
+        if manufacturer_part:
+            # Link ManufacturerPart
+            supplier_part.manufacturer_part = manufacturer_part
+            supplier_part.save()
+        print(f'{supplier_part=}')
+
         single_pricing = form.cleaned_data.get('single_pricing', None)
 
         if single_pricing:
@@ -606,6 +627,12 @@ class SupplierPartCreate(AjaxCreateView):
             # Hide the part field
             form.fields['part'].widget = HiddenInput()
 
+        if form.initial.get('manufacturer', None):
+            # Hide the manufacturer field
+            form.fields['manufacturer'].widget = HiddenInput()
+            # Hide the MPN field
+            form.fields['MPN'].widget = HiddenInput()
+
         return form
 
     def get_initial(self):
@@ -619,6 +646,7 @@ class SupplierPartCreate(AjaxCreateView):
         manufacturer_id = self.get_param('manufacturer')
         supplier_id = self.get_param('supplier')
         part_id = self.get_param('part')
+        manufacturer_part_id = self.get_param('manufacturer_part')
 
         supplier = None
 
@@ -634,6 +662,18 @@ class SupplierPartCreate(AjaxCreateView):
                 initials['manufacturer'] = Company.objects.get(pk=manufacturer_id)
             except (ValueError, Company.DoesNotExist):
                 pass
+
+        if manufacturer_part_id:
+            try:
+                # Get ManufacturerPart instance information
+                manufacturer_part_obj = ManufacturerPart.objects.get(pk=manufacturer_part_id)
+                print(manufacturer_part_obj.part.id)
+                initials['part'] = Part.objects.get(pk=manufacturer_part_obj.part.id)
+                print(initials['part'])
+                initials['manufacturer'] = manufacturer_part_obj.manufacturer.id
+                initials['MPN'] = manufacturer_part_obj.MPN
+            except (ValueError, ManufacturerPart.DoesNotExist, Part.DoesNotExist, Company.DoesNotExist):
+                pass
         
         if part_id:
             try:
diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py
index a7a7955c22..081a3b9255 100644
--- a/InvenTree/stock/api.py
+++ b/InvenTree/stock/api.py
@@ -773,7 +773,7 @@ class StockList(generics.ListCreateAPIView):
         company = params.get('company', None)
 
         if company is not None:
-            queryset = queryset.filter(Q(supplier_part__supplier=company) | Q(supplier_part__manufacturer=company))
+            queryset = queryset.filter(Q(supplier_part__supplier=company) | Q(supplier_part__manufacturer_part__manufacturer=company))
 
         # Filter by supplier
         supplier = params.get('supplier', None)
@@ -785,7 +785,7 @@ class StockList(generics.ListCreateAPIView):
         manufacturer = params.get('manufacturer', None)
 
         if manufacturer is not None:
-            queryset = queryset.filter(supplier_part__manufacturer=manufacturer)
+            queryset = queryset.filter(supplier_part__manufacturer_part__manufacturer=manufacturer)
 
         """
         Filter by the 'last updated' date of the stock item(s):
diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py
index 9cb2538ba7..5b00c1dd17 100644
--- a/InvenTree/stock/serializers.py
+++ b/InvenTree/stock/serializers.py
@@ -84,7 +84,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
             'sales_order',
             'supplier_part',
             'supplier_part__supplier',
-            'supplier_part__manufacturer',
+            'supplier_part__manufacturer_part__manufacturer',
             'allocations',
             'sales_order_allocations',
             'location',