mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-30 20:46:47 +00:00
Merge remote-tracking branch 'inventree/master'
This commit is contained in:
commit
3a10d235c1
@ -70,7 +70,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
queryset = PartCategory.objects.all()
|
queryset = PartCategory.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class PartDetail(generics.RetrieveUpdateDestroyAPIView):
|
class PartDetail(generics.RetrieveUpdateAPIView):
|
||||||
""" API endpoint for detail view of a single Part object """
|
""" API endpoint for detail view of a single Part object """
|
||||||
queryset = Part.objects.all()
|
queryset = Part.objects.all()
|
||||||
serializer_class = PartSerializer
|
serializer_class = PartSerializer
|
||||||
@ -135,6 +135,7 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
'trackable',
|
'trackable',
|
||||||
'purchaseable',
|
'purchaseable',
|
||||||
'salable',
|
'salable',
|
||||||
|
'active',
|
||||||
]
|
]
|
||||||
|
|
||||||
ordering_fields = [
|
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?
|
# Can this part be sold to customers?
|
||||||
salable = models.BooleanField(default=False, help_text="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)
|
notes = models.TextField(blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -53,6 +53,7 @@ class PartSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Part
|
model = Part
|
||||||
|
partial = True
|
||||||
fields = [
|
fields = [
|
||||||
'pk',
|
'pk',
|
||||||
'url', # Link to the part detail page
|
'url', # Link to the part detail page
|
||||||
@ -70,6 +71,7 @@ class PartSerializer(serializers.ModelSerializer):
|
|||||||
'consumable',
|
'consumable',
|
||||||
'trackable',
|
'trackable',
|
||||||
'salable',
|
'salable',
|
||||||
|
'active',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
<h3>Part Builds</h3>
|
<h3>Part Builds</h3>
|
||||||
|
|
||||||
<div id='button-toolbar'>
|
<div id='button-toolbar'>
|
||||||
|
{% if part.active %}
|
||||||
<button class="btn btn-success" id='start-build'>Start New Build</button>
|
<button class="btn btn-success" id='start-build'>Start New Build</button>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
|
<table class='table table-striped table-condensed' data-toolbar='#button-toolbar' id='build-table'>
|
||||||
|
@ -115,16 +115,15 @@
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
pagination: true,
|
pagination: true,
|
||||||
rememberOrder: true,
|
rememberOrder: true,
|
||||||
{% if category %}
|
|
||||||
queryParams: function(p) {
|
queryParams: function(p) {
|
||||||
return {
|
return {
|
||||||
|
active: true,
|
||||||
{% if category %}
|
{% if category %}
|
||||||
category: {{ category.id }},
|
category: {{ category.id }},
|
||||||
include_child_categories: true,
|
include_child_categories: true,
|
||||||
{% endif %}
|
{% endif %}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{% endif %}
|
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
checkbox: true,
|
checkbox: true,
|
||||||
@ -160,7 +159,7 @@
|
|||||||
else {
|
else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'total_stock',
|
field: 'total_stock',
|
||||||
|
@ -17,7 +17,12 @@
|
|||||||
<li><a href='#' id='duplicate-part' title='Duplicate Part'>Duplicate</a></li>
|
<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='edit-part' title='Edit part'>Edit</a></li>
|
||||||
<li><a href='#' id='stocktake-part' title='Stocktake'>Stocktake</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</h3>
|
</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() {
|
$('#delete-part').click(function() {
|
||||||
launchDeleteForm(
|
launchDeleteForm(
|
||||||
"{% url 'part-delete' part.id %}",
|
"{% url 'part-delete' part.id %}",
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<div class="row">
|
<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="col-sm-6">
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<div class="media-left">
|
<div class="media-left">
|
||||||
@ -16,7 +21,7 @@
|
|||||||
{% endif %}/>
|
{% endif %}/>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-body">
|
<div class="media-body">
|
||||||
<h4>{{ part.name }}</h4>
|
<h4>{{ part.name }}{% if part.active == False %} <i>- INACTIVE</i>{% endif %}</h4>
|
||||||
{% if part.description %}
|
{% if part.description %}
|
||||||
<p><i>{{ part.description }}</i></p>
|
<p><i>{{ part.description }}</i></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
<h3>Part Stock</h3>
|
<h3>Part Stock</h3>
|
||||||
|
|
||||||
<div id='button-toolbar'>
|
<div id='button-toolbar'>
|
||||||
|
{% if part.active %}
|
||||||
<button class='btn btn-success' id='add-stock-item'>New Stock Item</button>
|
<button class='btn btn-success' id='add-stock-item'>New Stock Item</button>
|
||||||
|
{% endif %}
|
||||||
<div id='opt-dropdown' class="dropdown" style='float: right;'>
|
<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
|
<button id='stock-options' class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Options
|
||||||
<span class="caret"></span></button>
|
<span class="caret"></span></button>
|
||||||
|
@ -91,6 +91,17 @@ class PartCreate(AjaxCreateView):
|
|||||||
|
|
||||||
return context
|
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
|
# Pre-fill the category field if a valid category is provided
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
""" Get initial data for the new Part object:
|
""" Get initial data for the new Part object:
|
||||||
@ -169,6 +180,20 @@ class PartEdit(AjaxUpdateView):
|
|||||||
ajax_form_title = 'Edit Part Properties'
|
ajax_form_title = 'Edit Part Properties'
|
||||||
context_object_name = 'part'
|
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):
|
class BomExport(AjaxView):
|
||||||
|
|
||||||
@ -425,6 +450,9 @@ class SupplierPartCreate(AjaxCreateView):
|
|||||||
context_object_name = 'part'
|
context_object_name = 'part'
|
||||||
|
|
||||||
def get_form(self):
|
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()
|
form = super(AjaxCreateView, self).get_form()
|
||||||
|
|
||||||
if form.initial.get('supplier', None):
|
if form.initial.get('supplier', None):
|
||||||
|
@ -47,11 +47,7 @@ function inventreeUpdate(url, data={}, options={}) {
|
|||||||
data["_is_final"] = true;
|
data["_is_final"] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var method = 'put';
|
var method = options.method || 'PUT';
|
||||||
|
|
||||||
if ('method' in options) {
|
|
||||||
method = options.method;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Middleware token required for data update
|
// Middleware token required for data update
|
||||||
//var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
|
//var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
|
||||||
@ -69,12 +65,21 @@ function inventreeUpdate(url, data={}, options={}) {
|
|||||||
success: function(response, status) {
|
success: function(response, status) {
|
||||||
response['_status_code'] = status;
|
response['_status_code'] = status;
|
||||||
console.log('UPDATE object to ' + url + ' - result = ' + 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) {
|
error: function(xhr, ajaxOptions, thrownError) {
|
||||||
console.error('Error on UPDATE to ' + url);
|
console.error('Error on UPDATE to ' + url);
|
||||||
console.error(thrownError);
|
console.error(thrownError);
|
||||||
|
if (options.error) {
|
||||||
|
options.error(xhr, ajaxOptions, thrownError);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return list of parts with optional filters
|
// Return list of parts with optional filters
|
||||||
|
@ -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
|
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
|
### Test
|
||||||
|
|
||||||
Run `make test` to run all code tests
|
Run `make test` to run all code tests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user