mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-03 22:55:43 +00:00 
			
		
		
		
	Merge remote-tracking branch 'inventree/master'
This commit is contained in:
		@@ -70,7 +70,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
 | 
			
		||||
    queryset = PartCategory.objects.all()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
 | 
			
		||||
class PartDetail(generics.RetrieveUpdateAPIView):
 | 
			
		||||
    """ API endpoint for detail view of a single Part object """
 | 
			
		||||
    queryset = Part.objects.all()
 | 
			
		||||
    serializer_class = PartSerializer
 | 
			
		||||
@@ -135,6 +135,7 @@ class PartList(generics.ListCreateAPIView):
 | 
			
		||||
        'trackable',
 | 
			
		||||
        'purchaseable',
 | 
			
		||||
        'salable',
 | 
			
		||||
        'active',
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    ordering_fields = [
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								InvenTree/part/migrations/0012_part_active.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								InvenTree/part/migrations/0012_part_active.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2 on 2019-04-28 13:00
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('part', '0011_auto_20190428_0841'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='part',
 | 
			
		||||
            name='active',
 | 
			
		||||
            field=models.BooleanField(default=True, help_text='Is this part active?'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -171,6 +171,9 @@ class Part(models.Model):
 | 
			
		||||
    # Can this part be sold to customers?
 | 
			
		||||
    salable = models.BooleanField(default=False, help_text="Can this part be sold to customers?")
 | 
			
		||||
 | 
			
		||||
    # Is this part active?
 | 
			
		||||
    active = models.BooleanField(default=True, help_text='Is this part active?')
 | 
			
		||||
 | 
			
		||||
    notes = models.TextField(blank=True)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,7 @@ class PartSerializer(serializers.ModelSerializer):
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Part
 | 
			
		||||
        partial = True
 | 
			
		||||
        fields = [
 | 
			
		||||
            'pk',
 | 
			
		||||
            'url',  # Link to the part detail page
 | 
			
		||||
@@ -70,6 +71,7 @@ class PartSerializer(serializers.ModelSerializer):
 | 
			
		||||
            'consumable',
 | 
			
		||||
            'trackable',
 | 
			
		||||
            'salable',
 | 
			
		||||
            'active',
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
<h3>Part Builds</h3>
 | 
			
		||||
 | 
			
		||||
<div id='button-toolbar'>
 | 
			
		||||
    {% if part.active %}
 | 
			
		||||
    <button class="btn btn-success" id='start-build'>Start New Build</button>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
 | 
			
		||||
 
 | 
			
		||||
@@ -115,16 +115,15 @@
 | 
			
		||||
        method: 'get',
 | 
			
		||||
        pagination: true,
 | 
			
		||||
        rememberOrder: true,
 | 
			
		||||
        {% if category %}
 | 
			
		||||
        queryParams: function(p) {
 | 
			
		||||
            return {
 | 
			
		||||
                active: true,
 | 
			
		||||
                {% if category %}
 | 
			
		||||
                category: {{ category.id }},
 | 
			
		||||
                include_child_categories: true,
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        columns: [
 | 
			
		||||
            {
 | 
			
		||||
                checkbox: true,
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,12 @@
 | 
			
		||||
                  <li><a href='#' id='duplicate-part' title='Duplicate Part'>Duplicate</a></li>
 | 
			
		||||
                  <li><a href="#" id='edit-part' title='Edit part'>Edit</a></li>
 | 
			
		||||
                  <li><a href='#' id='stocktake-part' title='Stocktake'>Stocktake</a></li>
 | 
			
		||||
                  <li><a href="#" id='delete-part' title='Delete part'>Delete</a></li>
 | 
			
		||||
                  <hr>
 | 
			
		||||
                  {% if part.active %}
 | 
			
		||||
                  <li><a href="#" id='deactivate-part' title='Deactivate part'>Deactivate</a></li>
 | 
			
		||||
                  {% else %}
 | 
			
		||||
                  <li><a href="#" id='activate-part' title='Activate part'>Activate</a></li>
 | 
			
		||||
                  {% endif %}
 | 
			
		||||
                </ul>
 | 
			
		||||
            </div>
 | 
			
		||||
        </h3>
 | 
			
		||||
@@ -141,6 +146,33 @@
 | 
			
		||||
                        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('#activate-part').click(function() {
 | 
			
		||||
        inventreeUpdate(
 | 
			
		||||
            "{% url 'api-part-detail' part.id %}",
 | 
			
		||||
            {
 | 
			
		||||
                active: true,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                method: 'PATCH',
 | 
			
		||||
                reloadOnSuccess: true,
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('#deactivate-part').click(function() {
 | 
			
		||||
        inventreeUpdate(
 | 
			
		||||
            "{% url 'api-part-detail' part.id %}",
 | 
			
		||||
            {
 | 
			
		||||
                active: false,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                method: 'PATCH',
 | 
			
		||||
                reloadOnSuccess: true,
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    $('#delete-part').click(function() {
 | 
			
		||||
        launchDeleteForm(
 | 
			
		||||
                         "{% url 'part-delete' part.id %}",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,11 @@
 | 
			
		||||
{% block content %}
 | 
			
		||||
 | 
			
		||||
<div class="row">
 | 
			
		||||
    {% if part.active == False %}
 | 
			
		||||
    <div class='alert alert-danger' style='display: block;'>
 | 
			
		||||
        This part ({{ part.name }}) is not active:
 | 
			
		||||
    </div>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
<div class="col-sm-6">
 | 
			
		||||
    <div class="media">
 | 
			
		||||
      <div class="media-left">
 | 
			
		||||
@@ -16,7 +21,7 @@
 | 
			
		||||
        {% endif %}/>
 | 
			
		||||
      </div>
 | 
			
		||||
    <div class="media-body">
 | 
			
		||||
        <h4>{{ part.name }}</h4>
 | 
			
		||||
        <h4>{{ part.name }}{% if part.active == False %} <i>- INACTIVE</i>{% endif %}</h4>
 | 
			
		||||
        {% if part.description %}
 | 
			
		||||
        <p><i>{{ part.description }}</i></p>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
<h3>Part Stock</h3>
 | 
			
		||||
 | 
			
		||||
<div id='button-toolbar'>
 | 
			
		||||
    {% if part.active %}
 | 
			
		||||
    <button class='btn btn-success' id='add-stock-item'>New Stock Item</button>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
    <div id='opt-dropdown' class="dropdown" style='float: right;'>
 | 
			
		||||
        <button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Options
 | 
			
		||||
            <span class="caret"></span></button>
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,17 @@ class PartCreate(AjaxCreateView):
 | 
			
		||||
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
    def get_form(self):
 | 
			
		||||
        """ Create Form for making new Part object.
 | 
			
		||||
        Remove the 'default_supplier' field as there are not yet any matching SupplierPart objects
 | 
			
		||||
        """
 | 
			
		||||
        form = super(AjaxCreateView, self).get_form()
 | 
			
		||||
 | 
			
		||||
        # Hide the default_supplier field (there are no matching supplier parts yet!)
 | 
			
		||||
        del form.fields['default_supplier']
 | 
			
		||||
 | 
			
		||||
        return form
 | 
			
		||||
 | 
			
		||||
    # Pre-fill the category field if a valid category is provided
 | 
			
		||||
    def get_initial(self):
 | 
			
		||||
        """ Get initial data for the new Part object:
 | 
			
		||||
@@ -169,6 +180,20 @@ class PartEdit(AjaxUpdateView):
 | 
			
		||||
    ajax_form_title = 'Edit Part Properties'
 | 
			
		||||
    context_object_name = 'part'
 | 
			
		||||
 | 
			
		||||
    def get_form(self):
 | 
			
		||||
        """ Create form for Part editing.
 | 
			
		||||
        Overrides default get_form() method to limit the choices
 | 
			
		||||
        for the 'default_supplier' field to SupplierParts that reference this part
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        form = super(AjaxUpdateView, self).get_form()
 | 
			
		||||
 | 
			
		||||
        part = self.get_object()
 | 
			
		||||
 | 
			
		||||
        form.fields['default_supplier'].queryset = SupplierPart.objects.filter(part=part)
 | 
			
		||||
 | 
			
		||||
        return form
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BomExport(AjaxView):
 | 
			
		||||
 | 
			
		||||
@@ -425,6 +450,9 @@ class SupplierPartCreate(AjaxCreateView):
 | 
			
		||||
    context_object_name = 'part'
 | 
			
		||||
 | 
			
		||||
    def get_form(self):
 | 
			
		||||
        """ Create Form instance to create a new SupplierPart object.
 | 
			
		||||
        Hide some fields if they are not appropriate in context
 | 
			
		||||
        """
 | 
			
		||||
        form = super(AjaxCreateView, self).get_form()
 | 
			
		||||
        
 | 
			
		||||
        if form.initial.get('supplier', None):
 | 
			
		||||
 
 | 
			
		||||
@@ -47,11 +47,7 @@ function inventreeUpdate(url, data={}, options={}) {
 | 
			
		||||
        data["_is_final"] = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var method = 'put';
 | 
			
		||||
 | 
			
		||||
    if ('method' in options) {
 | 
			
		||||
        method = options.method;
 | 
			
		||||
    }
 | 
			
		||||
    var method = options.method || 'PUT';
 | 
			
		||||
 | 
			
		||||
    // Middleware token required for data update
 | 
			
		||||
    //var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
 | 
			
		||||
@@ -69,10 +65,19 @@ function inventreeUpdate(url, data={}, options={}) {
 | 
			
		||||
        success: function(response, status) {
 | 
			
		||||
            response['_status_code'] = status;
 | 
			
		||||
            console.log('UPDATE object to ' + url + ' - result = ' + status);
 | 
			
		||||
            if (options.success) {
 | 
			
		||||
                options.success(response, status);
 | 
			
		||||
            }
 | 
			
		||||
            if (options.reloadOnSuccess) {
 | 
			
		||||
                location.reload();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        error: function(xhr, ajaxOptions, thrownError) {
 | 
			
		||||
            console.error('Error on UPDATE to ' + url);
 | 
			
		||||
            console.error(thrownError);
 | 
			
		||||
            if (options.error) {
 | 
			
		||||
                options.error(xhr, ajaxOptions, thrownError);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@ Run `make migrate` to perform all pending database migrations to ensure the data
 | 
			
		||||
 | 
			
		||||
Run `make superuser` to create an admin account for the database
 | 
			
		||||
 | 
			
		||||
### Launch Development Server
 | 
			
		||||
 | 
			
		||||
Run `python InvenTree/manage.py runserver` to launch a (development / debug) server. InvenTree can be then accessed via a web browser at `http://127.0.0.1:8000`
 | 
			
		||||
 | 
			
		||||
### Test
 | 
			
		||||
 | 
			
		||||
Run `make test` to run all code tests
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user