mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Added global setting to enable manufacturer parts
Created SourceItem model Updated templates
This commit is contained in:
		| @@ -202,6 +202,13 @@ class InvenTreeSetting(models.Model): | |||||||
|             'validator': bool, |             'validator': bool, | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  |         'PART_ENABLE_MANUFACTURER_PARTS': { | ||||||
|  |             'name': _('Enable Manufacturer Parts'), | ||||||
|  |             'description': _('Enable the use of manufacturer parts for purchasing'), | ||||||
|  |             'default': False, | ||||||
|  |             'validator': bool, | ||||||
|  |         }, | ||||||
|  |  | ||||||
|         'REPORT_DEBUG_MODE': { |         'REPORT_DEBUG_MODE': { | ||||||
|             'name': _('Debug Mode'), |             'name': _('Debug Mode'), | ||||||
|             'description': _('Generate reports in debug mode (HTML output)'), |             'description': _('Generate reports in debug mode (HTML output)'), | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ class ManufacturerPartList(generics.ListCreateAPIView): | |||||||
|         params = self.request.query_params |         params = self.request.query_params | ||||||
|  |  | ||||||
|         # Filter by manufacturer |         # Filter by manufacturer | ||||||
|         manufacturer = params.get('manufacturer', None) |         manufacturer = params.get('company', None) | ||||||
|  |  | ||||||
|         if manufacturer is not None: |         if manufacturer is not None: | ||||||
|             queryset = queryset.filter(manufacturer=manufacturer) |             queryset = queryset.filter(manufacturer=manufacturer) | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								InvenTree/company/migrations/0033_auto_20210329_1700.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								InvenTree/company/migrations/0033_auto_20210329_1700.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | # Generated by Django 3.0.7 on 2021-03-29 17:00 | ||||||
|  |  | ||||||
|  | from django.db import migrations, models | ||||||
|  | import django.db.models.deletion | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('contenttypes', '0002_remove_content_type_name'), | ||||||
|  |         ('company', '0032_manufacturerpart'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='SourceItem', | ||||||
|  |             fields=[ | ||||||
|  |                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||||
|  |                 ('part_id', models.PositiveIntegerField()), | ||||||
|  |                 ('part_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), | ||||||
|  |             ], | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='manufacturerpart', | ||||||
|  |             name='source_item', | ||||||
|  |             field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='company.SourceItem', verbose_name='Sourcing Item'), | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='supplierpart', | ||||||
|  |             name='source_item', | ||||||
|  |             field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supplier_parts', to='company.SourceItem', verbose_name='Sourcing Item'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -13,6 +13,8 @@ from django.utils.translation import gettext_lazy as _ | |||||||
| from django.core.validators import MinValueValidator | from django.core.validators import MinValueValidator | ||||||
| from django.db import models | from django.db import models | ||||||
| from django.db.models import Sum, Q, UniqueConstraint | from django.db.models import Sum, Q, UniqueConstraint | ||||||
|  | from django.contrib.contenttypes.fields import GenericForeignKey | ||||||
|  | from django.contrib.contenttypes.models import ContentType | ||||||
|  |  | ||||||
| from django.apps import apps | from django.apps import apps | ||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
| @@ -278,6 +280,20 @@ class Contact(models.Model): | |||||||
|                                 on_delete=models.CASCADE) |                                 on_delete=models.CASCADE) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SourceItem(models.Model): | ||||||
|  |     """ This model allows flexibility for sourcing of InvenTree parts. | ||||||
|  |     Each SourceItem instance represents a single ManufacturerPart or | ||||||
|  |     SupplierPart instance. | ||||||
|  |     SourceItem can be linked to either Part or ManufacturerPart instances. | ||||||
|  |     """ | ||||||
|  |  | ||||||
|  |     part_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) | ||||||
|  |  | ||||||
|  |     part_id = models.PositiveIntegerField() | ||||||
|  |  | ||||||
|  |     part = GenericForeignKey('part_type', 'part_id') | ||||||
|  |  | ||||||
|  |  | ||||||
| class ManufacturerPart(models.Model): | class ManufacturerPart(models.Model): | ||||||
|     """ Represents a unique part as provided by a Manufacturer |     """ Represents a unique part as provided by a Manufacturer | ||||||
|     Each ManufacturerPart is identified by a MPN (Manufacturer Part Number) |     Each ManufacturerPart is identified by a MPN (Manufacturer Part Number) | ||||||
| @@ -286,6 +302,7 @@ class ManufacturerPart(models.Model): | |||||||
|  |  | ||||||
|     Attributes: |     Attributes: | ||||||
|         part: Link to the master Part |         part: Link to the master Part | ||||||
|  |         source_item: The sourcing item linked to this ManufacturerPart instance | ||||||
|         manufacturer: Company that manufactures the ManufacturerPart |         manufacturer: Company that manufactures the ManufacturerPart | ||||||
|         MPN: Manufacture part number |         MPN: Manufacture part number | ||||||
|         link: Link to external website for this manufacturer part |         link: Link to external website for this manufacturer part | ||||||
| @@ -304,6 +321,12 @@ class ManufacturerPart(models.Model): | |||||||
|                              help_text=_('Select part'), |                              help_text=_('Select part'), | ||||||
|                              ) |                              ) | ||||||
|      |      | ||||||
|  |     source_item = models.ForeignKey(SourceItem, on_delete=models.CASCADE, | ||||||
|  |                                     blank=True, null=True, | ||||||
|  |                                     related_name='manufacturer_parts', | ||||||
|  |                                     verbose_name=_('Sourcing Item'), | ||||||
|  |                                     ) | ||||||
|  |  | ||||||
|     manufacturer = models.ForeignKey( |     manufacturer = models.ForeignKey( | ||||||
|         Company, |         Company, | ||||||
|         on_delete=models.CASCADE, |         on_delete=models.CASCADE, | ||||||
| @@ -341,8 +364,8 @@ class SupplierPart(models.Model): | |||||||
|     A Part may be available from multiple suppliers |     A Part may be available from multiple suppliers | ||||||
|  |  | ||||||
|     Attributes: |     Attributes: | ||||||
|         part_type: Part or ManufacturerPart |         part: Link to the master Part | ||||||
|         part_id: Part or ManufacturerPart ID |         source_item: The sourcing item linked to this SupplierPart instance | ||||||
|         supplier: Company that supplies this SupplierPart object |         supplier: Company that supplies this SupplierPart object | ||||||
|         SKU: Stock keeping unit (supplier part number) |         SKU: Stock keeping unit (supplier part number) | ||||||
|         link: Link to external website for this supplier part |         link: Link to external website for this supplier part | ||||||
| @@ -372,6 +395,12 @@ class SupplierPart(models.Model): | |||||||
|                              help_text=_('Select part'), |                              help_text=_('Select part'), | ||||||
|                              ) |                              ) | ||||||
|  |  | ||||||
|  |     source_item = models.ForeignKey(SourceItem, on_delete=models.CASCADE, | ||||||
|  |                                     blank=True, null=True, | ||||||
|  |                                     related_name='supplier_parts', | ||||||
|  |                                     verbose_name=_('Sourcing Item'), | ||||||
|  |                                     ) | ||||||
|  |  | ||||||
|     supplier = models.ForeignKey(Company, on_delete=models.CASCADE, |     supplier = models.ForeignKey(Company, on_delete=models.CASCADE, | ||||||
|                                  related_name='supplied_parts', |                                  related_name='supplied_parts', | ||||||
|                                  limit_choices_to={'is_supplier': True}, |                                  limit_choices_to={'is_supplier': True}, | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| {% extends "company/company_base.html" %} | {% extends "company/company_base.html" %} | ||||||
| {% load static %} | {% load static %} | ||||||
| {% load i18n %} | {% load i18n %} | ||||||
|  | {% load inventree_extras %} | ||||||
|  |  | ||||||
| {% block menubar %} | {% block menubar %} | ||||||
| {% include 'company/navbar.html' with tab='parts' %} | {% include 'company/navbar.html' with tab='parts' %} | ||||||
| @@ -12,17 +13,18 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| {% block details %} | {% block details %} | ||||||
|  | {% setting_object 'PART_ENABLE_MANUFACTURER_PARTS' as manufacturer_parts %} | ||||||
|  |  | ||||||
| {% if roles.purchase_order.change %} | {% if roles.purchase_order.change %} | ||||||
| <div id='button-toolbar'> | <div id='button-toolbar'> | ||||||
|     <div class='button-toolbar container-fluid'> |     <div class='button-toolbar container-fluid'> | ||||||
|         <div class='btn-group role='group'> |         <div class='btn-group role='group'> | ||||||
|             {% if roles.purchase_order.add %} |             {% if roles.purchase_order.add %} | ||||||
|                 {% if company.is_manufacturer %} |                 {% if manufacturer_parts.value == "True" and company.is_manufacturer %} | ||||||
|                 <button class="btn btn-success" id='manufacturer-part-create' title='{% trans "Create new manufacturer part" %}'> |                 <button class="btn btn-success" id='manufacturer-part-create' title='{% trans "Create new manufacturer part" %}'> | ||||||
|                     <span class='fas fa-plus-circle'></span> {% trans "New Manufacturer Part" %} |                     <span class='fas fa-plus-circle'></span> {% trans "New Manufacturer Part" %} | ||||||
|                 </button> |                 </button> | ||||||
|                 {% endif %} |                 {% else %} | ||||||
|                 {% if company.is_supplier %} |  | ||||||
|                 <button class="btn btn-success" id='supplier-part-create' title='{% trans "Create new supplier part" %}'> |                 <button class="btn btn-success" id='supplier-part-create' title='{% trans "Create new supplier part" %}'> | ||||||
|                     <span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %} |                     <span class='fas fa-plus-circle'></span> {% trans "New Supplier Part" %} | ||||||
|                 </button> |                 </button> | ||||||
| @@ -57,6 +59,7 @@ | |||||||
| {% endblock %} | {% endblock %} | ||||||
| {% block js_ready %} | {% block js_ready %} | ||||||
| {{ block.super }} | {{ block.super }} | ||||||
|  | {% setting_object 'PART_ENABLE_MANUFACTURER_PARTS' as manufacturer_parts %} | ||||||
|  |  | ||||||
|     $("#manufacturer-part-create").click(function () { |     $("#manufacturer-part-create").click(function () { | ||||||
|         launchModalForm( |         launchModalForm( | ||||||
| @@ -108,7 +111,7 @@ | |||||||
|             }); |             }); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     {% if company.is_manufacturer %} |     {% if manufacturer_parts.value == "True" and company.is_manufacturer %} | ||||||
|     loadManufacturerPartTable( |     loadManufacturerPartTable( | ||||||
|         "#part-table", |         "#part-table", | ||||||
|         "{% url 'api-manufacturer-part-list' %}", |         "{% url 'api-manufacturer-part-list' %}", | ||||||
| @@ -120,9 +123,7 @@ | |||||||
|             }, |             }, | ||||||
|         } |         } | ||||||
|     ); |     ); | ||||||
|     {% endif %} |     {% else %} | ||||||
|  |  | ||||||
|     {% if company.is_supplier %} |  | ||||||
|     loadSupplierPartTable( |     loadSupplierPartTable( | ||||||
|         "#part-table", |         "#part-table", | ||||||
|         "{% url 'api-supplier-part-list' %}", |         "{% url 'api-supplier-part-list' %}", | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| {% load static %} | {% load static %} | ||||||
| {% load inventree_extras %} | {% load inventree_extras %} | ||||||
|  |  | ||||||
|  | {% setting_object 'PART_ENABLE_MANUFACTURER_PARTS' as manufacturer_parts %} | ||||||
|  |  | ||||||
| <ul class='list-group'> | <ul class='list-group'> | ||||||
|     <li class='list-group-item'> |     <li class='list-group-item'> | ||||||
|         <a href='#' id='company-menu-toggle'> |         <a href='#' id='company-menu-toggle'> | ||||||
| @@ -16,16 +18,14 @@ | |||||||
|         </a> |         </a> | ||||||
|     </li> |     </li> | ||||||
|  |  | ||||||
|     {% if company.is_manufacturer %} |     {% if manufacturer_parts.value == "True" and company.is_manufacturer %} | ||||||
|     <li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Manufactured Parts" %}'> |     <li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Manufactured Parts" %}'> | ||||||
|         <a href='{% url "company-detail-parts" company.id %}'> |         <a href='{% url "company-detail-parts" company.id %}'> | ||||||
|             <span class='fas fa-shapes'></span> |             <span class='fas fa-shapes'></span> | ||||||
|             {% trans "Parts" %} |             {% trans "Parts" %} | ||||||
|         </a> |         </a> | ||||||
|     </li> |     </li> | ||||||
|     {% endif %} |     {% else %} | ||||||
|  |  | ||||||
|     {% if company.is_supplier %} |  | ||||||
|     <li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Supplied Parts" %}'> |     <li class='list-group-item {% if tab == "parts" %}active{% endif %}' title='{% trans "Supplied Parts" %}'> | ||||||
|         <a href='{% url "company-detail-parts" company.id %}'> |         <a href='{% url "company-detail-parts" company.id %}'> | ||||||
|             <span class='fas fa-shapes'></span> |             <span class='fas fa-shapes'></span> | ||||||
|   | |||||||
| @@ -68,13 +68,16 @@ | |||||||
|         </a> |         </a> | ||||||
|     </li> |     </li> | ||||||
|     {% endif %} |     {% endif %} | ||||||
|  |     {% setting_object 'PART_ENABLE_MANUFACTURER_PARTS' as manufacturer_parts %} | ||||||
|     {% if part.purchaseable and roles.purchase_order.view %} |     {% if part.purchaseable and roles.purchase_order.view %} | ||||||
|  |     {% if manufacturer_parts.value == "True" %} | ||||||
|     <li class='list-group-item {% if tab == "manufacturers" %}active{% endif %}' title='{% trans "Manufacturers" %}'> |     <li class='list-group-item {% if tab == "manufacturers" %}active{% endif %}' title='{% trans "Manufacturers" %}'> | ||||||
|         <a href='{% url "part-manufacturers" part.id %}'> |         <a href='{% url "part-manufacturers" part.id %}'> | ||||||
|             <span class='menu-tab-icon fas fa-building'></span> |             <span class='menu-tab-icon fas fa-building'></span> | ||||||
|             {% trans "Manufacturers" %} |             {% trans "Manufacturers" %} | ||||||
|         </a> |         </a> | ||||||
|     </li> |     </li> | ||||||
|  |     {% endif %} | ||||||
|     <li class='list-group-item {% if tab == "suppliers" %}active{% endif %}' title='{% trans "Suppliers" %}'> |     <li class='list-group-item {% if tab == "suppliers" %}active{% endif %}' title='{% trans "Suppliers" %}'> | ||||||
|         <a href='{% url "part-suppliers" part.id %}'> |         <a href='{% url "part-suppliers" part.id %}'> | ||||||
|             <span class='menu-tab-icon fas fa-warehouse'></span> |             <span class='menu-tab-icon fas fa-warehouse'></span> | ||||||
|   | |||||||
| @@ -34,6 +34,8 @@ | |||||||
|         {% include "InvenTree/settings/setting.html" with key="PART_COPY_PARAMETERS" %} |         {% include "InvenTree/settings/setting.html" with key="PART_COPY_PARAMETERS" %} | ||||||
|         {% include "InvenTree/settings/setting.html" with key="PART_COPY_TESTS" %} |         {% include "InvenTree/settings/setting.html" with key="PART_COPY_TESTS" %} | ||||||
|         {% include "InvenTree/settings/setting.html" with key="PART_CATEGORY_PARAMETERS" %} |         {% include "InvenTree/settings/setting.html" with key="PART_CATEGORY_PARAMETERS" %} | ||||||
|  |         <tr><td colspan='5'></td></tr> | ||||||
|  |         {% include "InvenTree/settings/setting.html" with key="PART_ENABLE_MANUFACTURER_PARTS" %} | ||||||
|     </tbody> |     </tbody> | ||||||
| </table> | </table> | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user