mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	Implement global settings for assembly and template values of Part model
This commit is contained in:
		| @@ -230,6 +230,9 @@ class EditPartForm(HelperForm): | ||||
|             'default_supplier', | ||||
|             'units', | ||||
|             'minimum_stock', | ||||
|             'component', | ||||
|             'assembly', | ||||
|             'is_template', | ||||
|             'trackable', | ||||
|             'purchaseable', | ||||
|             'salable', | ||||
|   | ||||
							
								
								
									
										74
									
								
								InvenTree/part/migrations/0061_auto_20210103_2306.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								InvenTree/part/migrations/0061_auto_20210103_2306.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| # Generated by Django 3.0.7 on 2021-01-03 12:06 | ||||
|  | ||||
| import InvenTree.fields | ||||
| import InvenTree.validators | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
| import mptt.fields | ||||
| import part.settings | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('stock', '0055_auto_20201117_1453'), | ||||
|         ('part', '0060_merge_20201112_1722'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='IPN', | ||||
|             field=models.CharField(blank=True, help_text='Internal Part Number', max_length=100, null=True, validators=[InvenTree.validators.validate_part_ipn], verbose_name='IPN'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='assembly', | ||||
|             field=models.BooleanField(default=part.settings.part_assembly_default, help_text='Can this part be built from other parts?', verbose_name='Assembly'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='category', | ||||
|             field=mptt.fields.TreeForeignKey(blank=True, help_text='Part category', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='parts', to='part.PartCategory', verbose_name='Category'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='default_location', | ||||
|             field=mptt.fields.TreeForeignKey(blank=True, help_text='Where is this item normally stored?', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='default_parts', to='stock.StockLocation', verbose_name='Default Location'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='description', | ||||
|             field=models.CharField(help_text='Part description', max_length=250, verbose_name='Description'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='is_template', | ||||
|             field=models.BooleanField(default=part.settings.part_template_default, help_text='Is this part a template part?', verbose_name='Is Template'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='keywords', | ||||
|             field=models.CharField(blank=True, help_text='Part keywords to improve visibility in search results', max_length=250, null=True, verbose_name='Keywords'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='link', | ||||
|             field=InvenTree.fields.InvenTreeURLField(blank=True, help_text='Link to external URL', null=True, verbose_name='Link'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='name', | ||||
|             field=models.CharField(help_text='Part name', max_length=100, validators=[InvenTree.validators.validate_part_name], verbose_name='Name'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='revision', | ||||
|             field=models.CharField(blank=True, help_text='Part revision or version number', max_length=100, null=True, verbose_name='Revision'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='part', | ||||
|             name='variant_of', | ||||
|             field=models.ForeignKey(blank=True, help_text='Is this part a variant of another part?', limit_choices_to={'active': True, 'is_template': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='variants', to='part.Part', verbose_name='Variant Of'), | ||||
|         ), | ||||
|     ] | ||||
| @@ -640,36 +640,69 @@ class Part(MPTTModel): | ||||
|                     parent_part.clean() | ||||
|                     parent_part.save() | ||||
|  | ||||
|     name = models.CharField(max_length=100, blank=False, | ||||
|                             help_text=_('Part name'), | ||||
|                             validators=[validators.validate_part_name] | ||||
|                             ) | ||||
|     name = models.CharField( | ||||
|         max_length=100, blank=False, | ||||
|         help_text=_('Part name'), | ||||
|         verbose_name=_('Name'), | ||||
|         validators=[validators.validate_part_name] | ||||
|     ) | ||||
|  | ||||
|     is_template = models.BooleanField(default=False, help_text=_('Is this part a template part?')) | ||||
|     is_template = models.BooleanField( | ||||
|         default=part_settings.part_template_default, | ||||
|         verbose_name=_('Is Template'), | ||||
|         help_text=_('Is this part a template part?') | ||||
|     ) | ||||
|  | ||||
|     variant_of = models.ForeignKey('part.Part', related_name='variants', | ||||
|                                    null=True, blank=True, | ||||
|                                    limit_choices_to={ | ||||
|                                        'is_template': True, | ||||
|                                        'active': True, | ||||
|                                    }, | ||||
|                                    on_delete=models.SET_NULL, | ||||
|                                    help_text=_('Is this part a variant of another part?')) | ||||
|     variant_of = models.ForeignKey( | ||||
|         'part.Part', related_name='variants', | ||||
|         null=True, blank=True, | ||||
|         limit_choices_to={ | ||||
|             'is_template': True, | ||||
|             'active': True, | ||||
|         }, | ||||
|         on_delete=models.SET_NULL, | ||||
|         help_text=_('Is this part a variant of another part?'), | ||||
|         verbose_name=_('Variant Of'), | ||||
|     ) | ||||
|  | ||||
|     description = models.CharField(max_length=250, blank=False, help_text=_('Part description')) | ||||
|     description = models.CharField( | ||||
|         max_length=250, blank=False, | ||||
|         verbose_name=_('Description'), | ||||
|         help_text=_('Part description') | ||||
|     ) | ||||
|  | ||||
|     keywords = models.CharField(max_length=250, blank=True, null=True, help_text=_('Part keywords to improve visibility in search results')) | ||||
|     keywords = models.CharField( | ||||
|         max_length=250, blank=True, null=True, | ||||
|         verbose_name=_('Keywords'), | ||||
|         help_text=_('Part keywords to improve visibility in search results') | ||||
|     ) | ||||
|  | ||||
|     category = TreeForeignKey(PartCategory, related_name='parts', | ||||
|                               null=True, blank=True, | ||||
|                               on_delete=models.DO_NOTHING, | ||||
|                               help_text=_('Part category')) | ||||
|     category = TreeForeignKey( | ||||
|         PartCategory, related_name='parts', | ||||
|         null=True, blank=True, | ||||
|         on_delete=models.DO_NOTHING, | ||||
|         verbose_name=_('Category'), | ||||
|         help_text=_('Part category') | ||||
|     ) | ||||
|  | ||||
|     IPN = models.CharField(max_length=100, blank=True, null=True, help_text=_('Internal Part Number'), validators=[validators.validate_part_ipn]) | ||||
|     IPN = models.CharField( | ||||
|         max_length=100, blank=True, null=True, | ||||
|         verbose_name=_('IPN'), | ||||
|         help_text=_('Internal Part Number'), | ||||
|         validators=[validators.validate_part_ipn] | ||||
|     ) | ||||
|  | ||||
|     revision = models.CharField(max_length=100, blank=True, null=True, help_text=_('Part revision or version number')) | ||||
|     revision = models.CharField( | ||||
|         max_length=100, blank=True, null=True, | ||||
|         help_text=_('Part revision or version number'), | ||||
|         verbose_name=_('Revision'), | ||||
|     ) | ||||
|  | ||||
|     link = InvenTreeURLField(blank=True, null=True, help_text=_('Link to external URL')) | ||||
|     link = InvenTreeURLField( | ||||
|         blank=True, null=True, | ||||
|         verbose_name=_('Link'), | ||||
|         help_text=_('Link to external URL') | ||||
|     ) | ||||
|  | ||||
|     image = StdImageField( | ||||
|         upload_to=rename_part_image, | ||||
| @@ -679,10 +712,13 @@ class Part(MPTTModel): | ||||
|         delete_orphans=True, | ||||
|     ) | ||||
|  | ||||
|     default_location = TreeForeignKey('stock.StockLocation', on_delete=models.SET_NULL, | ||||
|                                       blank=True, null=True, | ||||
|                                       help_text=_('Where is this item normally stored?'), | ||||
|                                       related_name='default_parts') | ||||
|     default_location = TreeForeignKey('stock.StockLocation', | ||||
|         on_delete=models.SET_NULL, | ||||
|         blank=True, null=True, | ||||
|         help_text=_('Where is this item normally stored?'), | ||||
|         related_name='default_parts', | ||||
|         verbose_name=_('Default Location'), | ||||
|     ) | ||||
|  | ||||
|     def get_default_location(self): | ||||
|         """ Get the default location for a Part (may be None). | ||||
| @@ -733,7 +769,7 @@ class Part(MPTTModel): | ||||
|     units = models.CharField(max_length=20, default="", blank=True, null=True, help_text=_('Stock keeping units for this part')) | ||||
|  | ||||
|     assembly = models.BooleanField( | ||||
|         default=False, | ||||
|         default=part_settings.part_assembly_default, | ||||
|         verbose_name=_('Assembly'), | ||||
|         help_text=_('Can this part be built from other parts?') | ||||
|     ) | ||||
|   | ||||
| @@ -8,6 +8,22 @@ from __future__ import unicode_literals | ||||
| from common.models import InvenTreeSetting | ||||
|  | ||||
|  | ||||
| def part_assembly_default(): | ||||
|     """ | ||||
|     Returns the default value for the 'assembly' field of a Part object | ||||
|     """ | ||||
|  | ||||
|     return InvenTreeSetting.get_setting('PART_ASSEMBLY') | ||||
|  | ||||
|  | ||||
| def part_template_default(): | ||||
|     """ | ||||
|     Returns the default value for the 'is_template' field of a Part object | ||||
|     """ | ||||
|  | ||||
|     return InvenTreeSetting.get_setting('PART_TEMPLATE') | ||||
|  | ||||
|  | ||||
| def part_component_default(): | ||||
|     """ | ||||
|     Returns the default value for the 'component' field of a Part object | ||||
|   | ||||
| @@ -235,6 +235,8 @@ class PartSettingsTest(TestCase): | ||||
|             InvenTreeSetting.set_setting('PART_PURCHASEABLE', val, self.user) | ||||
|             InvenTreeSetting.set_setting('PART_SALABLE', val, self.user) | ||||
|             InvenTreeSetting.set_setting('PART_TRACKABLE', val, self.user) | ||||
|             InvenTreeSetting.set_setting('PART_ASSEMBLY', val, self.user) | ||||
|             InvenTreeSetting.set_setting('PART_TEMPLATE', val, self.user) | ||||
|  | ||||
|             self.assertEqual(val, InvenTreeSetting.get_setting('PART_COMPONENT')) | ||||
|             self.assertEqual(val, InvenTreeSetting.get_setting('PART_PURCHASEABLE')) | ||||
| @@ -247,6 +249,8 @@ class PartSettingsTest(TestCase): | ||||
|             self.assertEqual(part.purchaseable, val) | ||||
|             self.assertEqual(part.salable, val) | ||||
|             self.assertEqual(part.trackable, val) | ||||
|             self.assertEqual(part.assembly, val) | ||||
|             self.assertEqual(part.is_template, val) | ||||
|      | ||||
|             Part.objects.filter(pk=part.pk).delete() | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user