2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-29 20:16:44 +00:00

New SupplierPart manufacturer_part field

New migration file with database update to manufacturer parts
Removed SourceItem model
This commit is contained in:
eeintech 2021-03-30 13:14:30 -04:00
parent e78455085f
commit a4d098194b
5 changed files with 93 additions and 64 deletions

View File

@ -128,8 +128,7 @@ class EditSupplierPartForm(HelperForm):
'part', 'part',
'supplier', 'supplier',
'SKU', 'SKU',
'manufacturer', 'manufacturer_part',
'MPN',
'description', 'description',
'link', 'link',
'note', 'note',

View File

@ -1,44 +1,107 @@
# Generated by Django 3.0.7 on 2021-03-29 18:53
import InvenTree.fields import InvenTree.fields
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
def supplierpart_make_manufacturer_parts(apps, schema_editor):
Part = apps.get_model('part', 'Part')
ManufacturerPart = apps.get_model('company', 'ManufacturerPart')
SupplierPart = apps.get_model('company', 'SupplierPart')
print(f'\nCreating Manufacturer parts\n{"-"*10}')
for supplier_part in SupplierPart.objects.all():
print(f'{supplier_part.supplier.name[:15].ljust(15)} | {supplier_part.SKU[:15].ljust(15)}\t', end='')
if supplier_part.manufacturer_part:
print(f'[ERROR: MANUFACTURER PART ALREADY EXISTS]')
continue
part = supplier_part.part
if not part:
print(f'[ERROR: SUPPLIER PART IS NOT CONNECTED TO PART]')
continue
manufacturer = supplier_part.manufacturer
MPN = supplier_part.MPN
link = supplier_part.link
description = supplier_part.description
if manufacturer or MPN:
print(f' | {part.name[:15].ljust(15)}', end='')
try:
print(f' | {manufacturer.name[:15].ljust(15)}', end='')
except TypeError:
print(f' | {"EMPTY MANUF".ljust(15)}', end='')
try:
print(f' | {MPN[:15].ljust(15)}', end='')
except TypeError:
print(f' | {"EMPTY MPN".ljust(15)}', end='')
print('\t', end='')
# Create ManufacturerPart
manufacturer_part = ManufacturerPart(part=part, manufacturer=manufacturer, MPN=MPN, link=link, description=description)
manufacturer_part.save()
# Link it to SupplierPart
supplier_part.manufacturer_part = manufacturer_part
supplier_part.save()
print(f'[SUCCESS: MANUFACTURER PART CREATED]')
else:
print(f'[IGNORED: MISSING MANUFACTURER DATA]')
print(f'{"-"*10}\nDone')
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('part', '0063_bomitem_inherited'), ('part', '0063_bomitem_inherited'),
('contenttypes', '0002_remove_content_type_name'),
('company', '0031_auto_20210103_2215'), ('company', '0031_auto_20210103_2215'),
] ]
operations = [ 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='supplierpart',
name='source_item',
field=models.ForeignKey(blank=True, help_text='Select part', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supplier_parts', to='company.SourceItem', verbose_name='Part'),
),
migrations.CreateModel( migrations.CreateModel(
name='ManufacturerPart', name='ManufacturerPart',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('MPN', models.CharField(help_text='Manufacturer Part Number', max_length=100, verbose_name='MPN')), ('MPN', models.CharField(blank=True, help_text='Manufacturer Part Number', max_length=100, null=True, verbose_name='MPN')),
('link', InvenTree.fields.InvenTreeURLField(blank=True, help_text='URL for external manufacturer part link', null=True, verbose_name='Link')), ('link', InvenTree.fields.InvenTreeURLField(blank=True, help_text='URL for external manufacturer part link', null=True, verbose_name='Link')),
('description', models.CharField(blank=True, help_text='Manufacturer part description', max_length=250, null=True, verbose_name='Description')), ('description', models.CharField(blank=True, help_text='Manufacturer part description', max_length=250, null=True, verbose_name='Description')),
('manufacturer', models.ForeignKey(help_text='Select manufacturer', limit_choices_to={'is_manufacturer': True}, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='company.Company', verbose_name='Manufacturer')), ('manufacturer', models.ForeignKey(blank=True, help_text='Select manufacturer', limit_choices_to={'is_manufacturer': True}, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='company.Company', verbose_name='Manufacturer')),
('part', models.ForeignKey(help_text='Select part', limit_choices_to={'purchaseable': True}, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='part.Part', verbose_name='Base Part')), ('part', models.ForeignKey(help_text='Select part', limit_choices_to={'purchaseable': True}, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='part.Part', verbose_name='Base Part')),
], ],
options={ options={
'unique_together': {('part', 'manufacturer', 'MPN')}, 'unique_together': {('part', 'manufacturer', 'MPN')},
}, },
), ),
migrations.AddField(
model_name='supplierpart',
name='manufacturer_part',
field=models.ForeignKey(blank=True, help_text='Select manufacturer part', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='company.ManufacturerPart', verbose_name='Manufacturer Part'),
),
# Make new ManufacturerPart with SupplierPart "manufacturer" and "MPN"
# fields, then link it to the new SupplierPart "manufacturer_part" field
migrations.RunPython(supplierpart_make_manufacturer_parts),
# Make ManufacturerPart "manufacturer" and "MPN" field mandatory
migrations.AlterField(
model_name='ManufacturerPart',
name='manufacturer',
field=models.ForeignKey(help_text='Select manufacturer', limit_choices_to={'is_manufacturer': True}, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='manufacturer_parts', to='company.Company', verbose_name='Manufacturer'),
),
migrations.AlterField(
model_name='ManufacturerPart',
name='MPN',
field=models.CharField(help_text='Manufacturer Part Number', max_length=100, null=True, verbose_name='MPN'),
),
migrations.RemoveField(
model_name='supplierpart',
name='MPN',
),
migrations.RemoveField(
model_name='supplierpart',
name='manufacturer',
),
] ]

View File

@ -13,8 +13,6 @@ 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
@ -280,20 +278,6 @@ 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)
@ -323,6 +307,7 @@ class ManufacturerPart(models.Model):
manufacturer = models.ForeignKey( manufacturer = models.ForeignKey(
Company, Company,
on_delete=models.CASCADE, on_delete=models.CASCADE,
null=True,
related_name='manufacturer_parts', related_name='manufacturer_parts',
limit_choices_to={ limit_choices_to={
'is_manufacturer': True 'is_manufacturer': True
@ -332,6 +317,7 @@ class ManufacturerPart(models.Model):
) )
MPN = models.CharField( MPN = models.CharField(
null=True,
max_length=100, max_length=100,
verbose_name=_('MPN'), verbose_name=_('MPN'),
help_text=_('Manufacturer Part Number') help_text=_('Manufacturer Part Number')
@ -388,13 +374,6 @@ 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=_('Part'),
help_text=_('Select part'),
)
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},
@ -408,23 +387,12 @@ class SupplierPart(models.Model):
help_text=_('Supplier stock keeping unit') help_text=_('Supplier stock keeping unit')
) )
manufacturer = models.ForeignKey( manufacturer_part = models.ForeignKey(ManufacturerPart, on_delete=models.CASCADE,
Company, blank=True, null=True,
on_delete=models.SET_NULL, related_name='manufacturer_parts',
related_name='manufactured_parts', verbose_name=_('Manufacturer Part'),
limit_choices_to={ help_text=_('Select manufacturer part'),
'is_manufacturer': True )
},
verbose_name=_('Manufacturer'),
help_text=_('Select manufacturer'),
null=True, blank=True
)
MPN = models.CharField(
max_length=100, blank=True, null=True,
verbose_name=_('MPN'),
help_text=_('Manufacturer part number')
)
link = InvenTreeURLField( link = InvenTreeURLField(
blank=True, null=True, blank=True, null=True,

View File

@ -7,6 +7,7 @@ from rest_framework import serializers
from sql_util.utils import SubqueryCount from sql_util.utils import SubqueryCount
from .models import Company from .models import Company
from .models import ManufacturerPart
from .models import SupplierPart, SupplierPriceBreak from .models import SupplierPart, SupplierPriceBreak
from InvenTree.serializers import InvenTreeModelSerializer from InvenTree.serializers import InvenTreeModelSerializer
@ -157,7 +158,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True)) supplier = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_supplier=True))
manufacturer = serializers.PrimaryKeyRelatedField(queryset=Company.objects.filter(is_manufacturer=True)) manufacturer_part = serializers.PrimaryKeyRelatedField(queryset=ManufacturerPart.objects.all())
class Meta: class Meta:
model = SupplierPart model = SupplierPart
@ -169,10 +170,9 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
'supplier', 'supplier',
'supplier_detail', 'supplier_detail',
'SKU', 'SKU',
'manufacturer', 'manufacturer_part',
'manufacturer_detail', 'manufacturer_detail',
'description', 'description',
'MPN',
'link', 'link',
] ]

View File

@ -75,7 +75,6 @@ class RuleSet(models.Model):
'part_partstar', 'part_partstar',
'company_supplierpart', 'company_supplierpart',
'company_manufacturerpart', 'company_manufacturerpart',
'company_sourceitem',
], ],
'stock_location': [ 'stock_location': [
'stock_stocklocation', 'stock_stocklocation',