diff --git a/InvenTree/build/migrations/0012_auto_20190508_2332.py b/InvenTree/build/migrations/0012_auto_20190508_2332.py new file mode 100644 index 0000000000..099fce3fe9 --- /dev/null +++ b/InvenTree/build/migrations/0012_auto_20190508_2332.py @@ -0,0 +1,30 @@ +# Generated by Django 2.2 on 2019-05-08 13:32 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('build', '0011_auto_20190508_0748'), + ] + + operations = [ + migrations.AlterField( + model_name='build', + name='notes', + field=models.TextField(blank=True, help_text='Extra build notes'), + ), + migrations.AlterField( + model_name='build', + name='part', + field=models.ForeignKey(help_text='Select part to build', limit_choices_to={'active': True, 'buildable': True}, on_delete=django.db.models.deletion.CASCADE, related_name='builds', to='part.Part'), + ), + migrations.AlterField( + model_name='build', + name='status', + field=models.PositiveIntegerField(choices=[(10, 'Pending'), (20, 'Allocated'), (30, 'Cancelled'), (40, 'Complete')], default=10, help_text='Build status', validators=[django.core.validators.MinValueValidator(0)]), + ), + ] diff --git a/InvenTree/build/models.py b/InvenTree/build/models.py index d4a8e70448..fedcb76403 100644 --- a/InvenTree/build/models.py +++ b/InvenTree/build/models.py @@ -47,6 +47,7 @@ class Build(models.Model): 'buildable': True, 'active': True }, + help_text='Select part to build', ) title = models.CharField( @@ -75,7 +76,8 @@ class Build(models.Model): status = models.PositiveIntegerField(default=PENDING, choices=BUILD_STATUS_CODES.items(), - validators=[MinValueValidator(0)]) + validators=[MinValueValidator(0)], + help_text='Build status') batch = models.CharField(max_length=100, blank=True, null=True, help_text='Batch code for this build output') @@ -92,7 +94,7 @@ class Build(models.Model): URL = models.URLField(blank=True, help_text='Link to external URL') - notes = models.TextField(blank=True) + notes = models.TextField(blank=True, help_text='Extra build notes') """ Notes attached to each build output """ @transaction.atomic diff --git a/InvenTree/company/migrations/0006_auto_20190508_2332.py b/InvenTree/company/migrations/0006_auto_20190508_2332.py new file mode 100644 index 0000000000..232ccdd4f1 --- /dev/null +++ b/InvenTree/company/migrations/0006_auto_20190508_2332.py @@ -0,0 +1,43 @@ +# Generated by Django 2.2 on 2019-05-08 13:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('company', '0005_contact'), + ] + + operations = [ + migrations.AlterField( + model_name='company', + name='contact', + field=models.CharField(blank=True, help_text='Point of contact', max_length=100), + ), + migrations.AlterField( + model_name='company', + name='description', + field=models.CharField(help_text='Description of the company', max_length=500), + ), + migrations.AlterField( + model_name='company', + name='email', + field=models.EmailField(blank=True, help_text='Contact email address', max_length=254), + ), + migrations.AlterField( + model_name='company', + name='is_customer', + field=models.BooleanField(default=False, help_text='Do you sell items to this company?'), + ), + migrations.AlterField( + model_name='company', + name='is_supplier', + field=models.BooleanField(default=True, help_text='Do you purchase items from this company?'), + ), + migrations.AlterField( + model_name='company', + name='phone', + field=models.CharField(blank=True, help_text='Contact phone number', max_length=50), + ), + ] diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index bb86230b70..7ea72e4cc9 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -46,7 +46,7 @@ class Company(models.Model): name = models.CharField(max_length=100, blank=False, unique=True, help_text='Company name') - description = models.CharField(max_length=500) + description = models.CharField(max_length=500, help_text='Description of the company') website = models.URLField(blank=True, help_text='Company website URL') @@ -54,12 +54,12 @@ class Company(models.Model): blank=True, help_text='Company address') phone = models.CharField(max_length=50, - blank=True) + blank=True, help_text='Contact phone number') - email = models.EmailField(blank=True) + email = models.EmailField(blank=True, help_text='Contact email address') contact = models.CharField(max_length=100, - blank=True) + blank=True, help_text='Point of contact') URL = models.URLField(blank=True, help_text='Link to external company information') @@ -67,9 +67,9 @@ class Company(models.Model): notes = models.TextField(blank=True) - is_customer = models.BooleanField(default=False) + is_customer = models.BooleanField(default=False, help_text='Do you sell items to this company?') - is_supplier = models.BooleanField(default=True) + is_supplier = models.BooleanField(default=True, help_text='Do you purchase items from this company?') def __str__(self): """ Get string representation of a Company """ diff --git a/InvenTree/part/migrations/0019_auto_20190508_2332.py b/InvenTree/part/migrations/0019_auto_20190508_2332.py new file mode 100644 index 0000000000..b61bbee82b --- /dev/null +++ b/InvenTree/part/migrations/0019_auto_20190508_2332.py @@ -0,0 +1,35 @@ +# Generated by Django 2.2 on 2019-05-08 13:32 + +from django.db import migrations, models +import django.db.models.deletion +import part.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('part', '0018_auto_20190505_2231'), + ] + + operations = [ + migrations.AlterField( + model_name='part', + name='units', + field=models.CharField(blank=True, default='pcs', help_text='Stock keeping units for this part', max_length=20), + ), + migrations.AlterField( + model_name='partattachment', + name='attachment', + field=models.FileField(blank=True, help_text='Select file to attach', null=True, upload_to=part.models.attach_file), + ), + migrations.AlterField( + model_name='supplierpart', + name='part', + field=models.ForeignKey(help_text='Select part', limit_choices_to={'purchaseable': True}, on_delete=django.db.models.deletion.CASCADE, related_name='supplier_parts', to='part.Part'), + ), + migrations.AlterField( + model_name='supplierpart', + name='supplier', + field=models.ForeignKey(help_text='Select supplier', limit_choices_to={'is_supplier': True}, on_delete=django.db.models.deletion.CASCADE, related_name='parts', to='company.Company'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 3bca8cd445..27d9d94d10 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -193,7 +193,7 @@ class Part(models.Model): minimum_stock = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0)], help_text='Minimum allowed stock level') # Units of quantity for this part. Default is "pcs" - units = models.CharField(max_length=20, default="pcs", blank=True) + units = models.CharField(max_length=20, default="pcs", blank=True, help_text='Stock keeping units for this part') # Can this part be built from other parts? buildable = models.BooleanField(default=False, help_text='Can this part be built from other parts?') @@ -438,7 +438,8 @@ class PartAttachment(models.Model): part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='attachments') - attachment = models.FileField(upload_to=attach_file, null=True, blank=True) + attachment = models.FileField(upload_to=attach_file, null=True, blank=True, + help_text='Select file to attach') comment = models.CharField(max_length=100, blank=True, help_text='File comment') @@ -543,11 +544,13 @@ class SupplierPart(models.Model): part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='supplier_parts', limit_choices_to={'purchaseable': True}, + help_text='Select part', ) supplier = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='parts', - limit_choices_to={'is_supplier': True} + limit_choices_to={'is_supplier': True}, + help_text='Select supplier', ) SKU = models.CharField(max_length=100, help_text='Supplier stock keeping unit') @@ -639,10 +642,15 @@ class SupplierPart(models.Model): return cost + self.base_cost def __str__(self): - return "{supplier} ({sku})".format( + s = "{supplier} ({sku})".format( sku=self.SKU, supplier=self.supplier.name) + if self.manufacturer_string: + s = s + ' - ' + self.manufacturer_string + + return s + class SupplierPriceBreak(models.Model): """ Represents a quantity price break for a SupplierPart diff --git a/InvenTree/stock/migrations/0014_auto_20190508_2332.py b/InvenTree/stock/migrations/0014_auto_20190508_2332.py new file mode 100644 index 0000000000..829bd34df8 --- /dev/null +++ b/InvenTree/stock/migrations/0014_auto_20190508_2332.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2 on 2019-05-08 13:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('stock', '0013_remove_stockitem_uuid'), + ] + + operations = [ + migrations.AlterField( + model_name='stockitem', + name='supplier_part', + field=models.ForeignKey(blank=True, help_text='Select a matching supplier part for this stock item', null=True, on_delete=django.db.models.deletion.SET_NULL, to='part.SupplierPart'), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 2c16fd079c..537397f66b 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -163,7 +163,8 @@ class StockItem(models.Model): part = models.ForeignKey('part.Part', on_delete=models.CASCADE, related_name='locations', help_text='Base part') # The 'supplier part' used in this instance. May be null if no supplier parts are defined the master part - supplier_part = models.ForeignKey('part.SupplierPart', blank=True, null=True, on_delete=models.SET_NULL) + supplier_part = models.ForeignKey('part.SupplierPart', blank=True, null=True, on_delete=models.SET_NULL, + help_text='Select a matching supplier part for this stock item') # Where the part is stored. If the part has been used to build another stock item, the location may not make sense location = models.ForeignKey(StockLocation, on_delete=models.DO_NOTHING, diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index e618be1ee8..314d3c99f6 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -207,6 +207,14 @@ class StockItemCreate(AjaxCreateView): parts = form.fields['supplier_part'].queryset parts = parts.filter(part=part.id) form.fields['supplier_part'].queryset = parts + + # If there is one (and only one) supplier part available, pre-select it + all_parts = parts.all() + if len(all_parts) == 1: + + # TODO - This does NOT work for some reason? Ref build.views.BuildItemCreate + form.fields['supplier_part'].initial = all_parts[0].id + except Part.DoesNotExist: pass