mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	Merge branch 'negative-stock-fix'
This commit is contained in:
		| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| function defaultFilters() { | ||||
|     return { | ||||
|         stock: "cascade=1", | ||||
|         stock: "cascade=1&in_stock=1", | ||||
|         build: "", | ||||
|         parts: "cascade=1", | ||||
|         company: "", | ||||
|   | ||||
							
								
								
									
										55
									
								
								InvenTree/company/migrations/0022_auto_20200613_1045.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								InvenTree/company/migrations/0022_auto_20200613_1045.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| # Generated by Django 3.0.7 on 2020-06-13 10:45 | ||||
|  | ||||
| from django.db import migrations, models | ||||
| import django.db.models.deletion | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('part', '0045_auto_20200605_0932'), | ||||
|         ('company', '0021_remove_supplierpart_manufacturer_name'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='address', | ||||
|             field=models.CharField(blank=True, help_text='Company address', max_length=200, verbose_name='Address'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='contact', | ||||
|             field=models.CharField(blank=True, help_text='Point of contact', max_length=100, verbose_name='Contact'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='description', | ||||
|             field=models.CharField(help_text='Description of the company', max_length=500, verbose_name='Company description'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='email', | ||||
|             field=models.EmailField(blank=True, help_text='Contact email address', max_length=254, verbose_name='Email'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='name', | ||||
|             field=models.CharField(help_text='Company name', max_length=100, unique=True, verbose_name='Company name'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='phone', | ||||
|             field=models.CharField(blank=True, help_text='Contact phone number', max_length=50, verbose_name='Phone number'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='company', | ||||
|             name='website', | ||||
|             field=models.URLField(blank=True, help_text='Company website URL', verbose_name='Website'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='supplierpart', | ||||
|             name='part', | ||||
|             field=models.ForeignKey(help_text='Select part', limit_choices_to={'is_template': False, 'purchaseable': True}, on_delete=django.db.models.deletion.CASCADE, related_name='supplier_parts', to='part.Part', verbose_name='Base Part'), | ||||
|         ), | ||||
|     ] | ||||
| @@ -80,21 +80,25 @@ class Company(models.Model): | ||||
|     """ | ||||
|  | ||||
|     name = models.CharField(max_length=100, blank=False, unique=True, | ||||
|                             help_text=_('Company name')) | ||||
|                             help_text=_('Company name'), | ||||
|                             verbose_name=_('Company name')) | ||||
|  | ||||
|     description = models.CharField(max_length=500, help_text=_('Description of the company')) | ||||
|     description = models.CharField(max_length=500, verbose_name=_('Company description'), help_text=_('Description of the company')) | ||||
|  | ||||
|     website = models.URLField(blank=True, help_text=_('Company website URL')) | ||||
|     website = models.URLField(blank=True, verbose_name=_('Website'), help_text=_('Company website URL')) | ||||
|  | ||||
|     address = models.CharField(max_length=200, | ||||
|                                verbose_name=_('Address'), | ||||
|                                blank=True, help_text=_('Company address')) | ||||
|  | ||||
|     phone = models.CharField(max_length=50, | ||||
|                              verbose_name=_('Phone number'), | ||||
|                              blank=True, help_text=_('Contact phone number')) | ||||
|  | ||||
|     email = models.EmailField(blank=True, help_text=_('Contact email address')) | ||||
|     email = models.EmailField(blank=True, verbose_name=_('Email'), help_text=_('Contact email address')) | ||||
|  | ||||
|     contact = models.CharField(max_length=100, | ||||
|                                verbose_name=_('Contact'), | ||||
|                                blank=True, help_text=_('Point of contact')) | ||||
|  | ||||
|     link = InvenTreeURLField(blank=True, help_text=_('Link to external company information')) | ||||
| @@ -269,6 +273,7 @@ class SupplierPart(models.Model): | ||||
|  | ||||
|     part = models.ForeignKey('part.Part', on_delete=models.CASCADE, | ||||
|                              related_name='supplier_parts', | ||||
|                              verbose_name=_('Base Part'), | ||||
|                              limit_choices_to={ | ||||
|                                  'purchaseable': True, | ||||
|                                  'is_template': False, | ||||
|   | ||||
| @@ -594,7 +594,16 @@ class Part(MPTTModel): | ||||
|     def quantity_to_order(self): | ||||
|         """ Return the quantity needing to be ordered for this part. """ | ||||
|  | ||||
|         required = -1 * self.net_stock | ||||
|         # How many do we need to have "on hand" at any point? | ||||
|         required = self.net_stock - self.minimum_stock | ||||
|  | ||||
|         if required < 0: | ||||
|             return abs(required) | ||||
|  | ||||
|         # Do not need to order any | ||||
|         return 0 | ||||
|  | ||||
|         required = self.net_stock | ||||
|         return max(required, 0) | ||||
|  | ||||
|     @property | ||||
|   | ||||
| @@ -191,7 +191,7 @@ | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td><b>{% trans "Active" %}</b></td> | ||||
|             <td>{% include "slide.html" with state=part.active field='active' %}</td> | ||||
|             <td>{% include "slide.html" with state=part.active field='active' disabled=False %}</td> | ||||
|             {% if part.active %} | ||||
|             <td>{% trans "Part is active" %}</td> | ||||
|             {% else %} | ||||
|   | ||||
| @@ -40,7 +40,6 @@ | ||||
|             part: {{ part.id }}, | ||||
|             location_detail: true, | ||||
|             part_detail: true, | ||||
|             in_stock: true, | ||||
|         }, | ||||
|         groupByField: 'location', | ||||
|         buttons: [ | ||||
|   | ||||
| @@ -51,15 +51,6 @@ | ||||
|     </li> | ||||
|     {% endif %} | ||||
|     {% if part.trackable %} | ||||
|     {% if 0 %} | ||||
|     <!-- TODO - Add the 'tracking' tab back in --> | ||||
|     <li{% ifequal tab 'track' %} class="active"{% endifequal %}> | ||||
|         <a href="{% url 'part-track' part.id %}">{% trans "Tracking" %} | ||||
|         {% if parts.serials.all|length > 0 %} | ||||
|         <span class="badge">{{ part.serials.all|length }}</span> | ||||
|         {% endif %} | ||||
|     </a></li> | ||||
|     {% endif %} | ||||
|     <li{% ifequal tab 'tests' %} class='active'{% endifequal %}> | ||||
|         <a href='{% url "part-test-templates" part.id %}'>{% trans "Tests" %} | ||||
|             {% if part.getTestTemplates.count > 0 %}<span class='badge'>{{ part.getTestTemplates.count }}</span>{% endif %} | ||||
|   | ||||
| @@ -71,6 +71,7 @@ class StockItemSerializer(InvenTreeModelSerializer): | ||||
|             'belongs_to', | ||||
|             'build', | ||||
|             'build_order', | ||||
|             'customer', | ||||
|             'sales_order', | ||||
|             'supplier_part', | ||||
|             'supplier_part__supplier', | ||||
| @@ -141,6 +142,7 @@ class StockItemSerializer(InvenTreeModelSerializer): | ||||
|             'batch', | ||||
|             'build_order', | ||||
|             'belongs_to', | ||||
|             'customer', | ||||
|             'in_stock', | ||||
|             'link', | ||||
|             'location', | ||||
|   | ||||
| @@ -248,7 +248,6 @@ | ||||
|             {% endif %} | ||||
|             part_detail: true, | ||||
|             location_detail: true, | ||||
|             in_stock: true, | ||||
|         }, | ||||
|         url: "{% url 'api-stock-list' %}", | ||||
|     }); | ||||
|   | ||||
| @@ -494,10 +494,15 @@ function loadStockTable(table, options) { | ||||
|                 sortable: true, | ||||
|                 formatter: function(value, row, index, field) { | ||||
|                     if (value) { | ||||
|                         return renderLink(value, '/stock/location/' + row.location + '/'); | ||||
|                         return renderLink(value, `/stock/location/${row.location}/`); | ||||
|                     } | ||||
|                     else { | ||||
|                         return '<i>{% trans "No stock location set" %}</i>'; | ||||
|                         if (row.customer) { | ||||
|                             var text = "{% trans "Shipped to customer" %}"; | ||||
|                             return renderLink(text, `/company/${row.customer}/assigned-stock/`); | ||||
|                         } else { | ||||
|                             return '<i>{% trans "No stock location set" %}</i>'; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|   | ||||
| @@ -14,6 +14,11 @@ function getAvailableTableFilters(tableKey) { | ||||
|     // Filters for the "Stock" table | ||||
|     if (tableKey == 'stock') { | ||||
|         return { | ||||
|             in_stock: { | ||||
|                 type: 'bool', | ||||
|                 title: '{% trans "In Stock" %}', | ||||
|                 description: '{% trans "Show items which are in stock" %}', | ||||
|             }, | ||||
|             cascade: { | ||||
|                 type: 'bool', | ||||
|                 title: '{% trans "Include sublocations" %}', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user