Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2019-09-17 14:22:04 +10:00
commit 0a7ea27e9f
16 changed files with 107 additions and 73 deletions

View File

@ -1,3 +1,11 @@
:root {
--primary-color: #335d88;
--secondary-color: #b69c80;
--highlight-color: #f5efe8;
--basic-color: #333;
}
.qr-code { .qr-code {
max-width: 400px; max-width: 400px;
max-height: 400px; max-height: 400px;
@ -98,11 +106,11 @@
max-width: 250px; max-width: 250px;
} }
.bomrowvalid { .rowvalid {
color: #050; color: #050;
} }
.bomrowinvalid { .rowinvalid {
color: #A00; color: #A00;
font-style: italic; font-style: italic;
} }

View File

@ -280,9 +280,9 @@ function loadBomTable(table, options) {
search: true, search: true,
rowStyle: function(row, index) { rowStyle: function(row, index) {
if (row.validated) { if (row.validated) {
return {classes: 'bomrowvalid'}; return {classes: 'rowvalid'};
} else { } else {
return {classes: 'bomrowinvalid'}; return {classes: 'rowinvalid'};
} }
}, },
formatNoMatches: function() { return "No BOM items found"; }, formatNoMatches: function() { return "No BOM items found"; },

View File

@ -21,7 +21,7 @@
</thead> </thead>
<tbody> <tbody>
{% for item in build.required_parts %} {% for item in build.required_parts %}
<tr> <tr {% if build.status == BuildStatus.PENDING %}class='{% if item.part.total_stock > item.quantity %}rowvalid{% else %}rowinvalid{% endif %}'{% endif %}>
<td> <td>
{% include "hover_image.html" with image=item.part.image hover=True %} {% include "hover_image.html" with image=item.part.image hover=True %}
<a class='hover-icon'a href="{% url 'part-detail' item.part.id %}">{{ item.part.full_name }}</a> <a class='hover-icon'a href="{% url 'part-detail' item.part.id %}">{{ item.part.full_name }}</a>

View File

@ -34,7 +34,7 @@ InvenTree | Build - {{ build }}
<button type='button' class='btn btn-default btn-glyph' id='build-complete' title="Complete Build"> <button type='button' class='btn btn-default btn-glyph' id='build-complete' title="Complete Build">
<span class='glyphicon glyphicon-send'/> <span class='glyphicon glyphicon-send'/>
</button> </button>
<button type='button' class='btn btn-default btn-glyph' id='build-cancel'> <button type='button' class='btn btn-default btn-glyph' id='build-cancel' title='Cancel Build'>
<span class='glyphicon glyphicon-remove'/> <span class='glyphicon glyphicon-remove'/>
</button> </button>
{% endif %} {% endif %}

View File

@ -38,8 +38,12 @@ class SupplierPartResource(ModelResource):
part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part)) part = Field(attribute='part', widget=widgets.ForeignKeyWidget(Part))
part_name = Field(attribute='part__full_name', readonly=True)
supplier = Field(attribute='supplier', widget=widgets.ForeignKeyWidget(Company)) supplier = Field(attribute='supplier', widget=widgets.ForeignKeyWidget(Company))
supplier_name = Field(attribute='supplier__name', readonly=True)
class Meta: class Meta:
model = SupplierPart model = SupplierPart
skip_unchanged = True skip_unchanged = True
@ -61,6 +65,16 @@ class SupplierPriceBreakResource(ModelResource):
currency = Field(attribute='currency', widget=widgets.ForeignKeyWidget(Currency)) currency = Field(attribute='currency', widget=widgets.ForeignKeyWidget(Currency))
supplier_id = Field(attribute='part__supplier__pk', readonly=True)
supplier_name = Field(attribute='part__supplier__name', readonly=True)
part_name = Field(attribute='part__part__full_name', readonly=True)
SKU = Field(attribute='part__SKU', readonly=True)
MPN = Field(attribute='part__MPN', readonly=True)
class Meta: class Meta:
model = SupplierPriceBreak model = SupplierPriceBreak
skip_unchanged = True skip_unchanged = True

View File

@ -93,8 +93,8 @@ InvenTree | {{ company.name }} - Parts
{{ pb.cost }} {{ pb.cost }}
{% if pb.currency %}{{ pb.currency.suffix }}{% endif %} {% if pb.currency %}{{ pb.currency.suffix }}{% endif %}
<div class='btn-group' style='float: right;'> <div class='btn-group' style='float: right;'>
<button title='Edit Price Break' class='btn btn-default btn-sm' type='button' url="{% url 'price-break-edit' pb.id %}"><span class='glyphicon glyphicon-edit'></span></button> <button title='Edit Price Break' class='btn btn-default btn-sm pb-edit-button' type='button' url="{% url 'price-break-edit' pb.id %}"><span class='glyphicon glyphicon-edit'></span></button>
<button title='Delete Price Break' class='btn btn-default btn-sm' type='button' url="{% url 'price-break-delete' pb.id %}"><span class='glyphicon glyphicon-trash'></span></button> <button title='Delete Price Break' class='btn btn-default btn-sm pb-delete-button' type='button' url="{% url 'price-break-delete' pb.id %}"><span class='glyphicon glyphicon-trash'></span></button>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -1,11 +1,11 @@
<table class='table table-striped table-condensed' id='po-table' {% if toolbar %}data-toolbar='{{ toolbar }}'{% endif %}> <table class='table table-striped table-condensed' id='po-table' {% if toolbar %}data-toolbar='{{ toolbar }}'{% endif %}>
<thead> <thead>
<tr> <tr>
<th data-field='company' data-searchable='true'>Company</th> <th data-field='company' data-sortable='true' data-searchable='true'>Company</th>
<th data-field='reference' data-searchable='true'>Order Reference</th> <th data-field='reference' data-sortable='true' data-searchable='true'>Order Reference</th>
<th data-field='description' data-searchable='true'>Description</th> <th data-field='description' data-sortable='true' data-searchable='true'>Description</th>
<th data-field='status'>Status</th> <th data-field='status' data-sortable='true'>Status</th>
<th data-field='items'>Items</th> <th data-field='items' data-sortable='true'>Items</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@ -7,6 +7,7 @@ from __future__ import unicode_literals
from InvenTree.forms import HelperForm from InvenTree.forms import HelperForm
from mptt.fields import TreeNodeChoiceField
from django import forms from django import forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -66,6 +67,12 @@ class EditPartAttachmentForm(HelperForm):
] ]
class SetPartCategoryForm(forms.Form):
""" Form for setting the category of multiple Part objects """
part_category = TreeNodeChoiceField(queryset=PartCategory.objects.all(), required=True, help_text=_('Select part category'))
class EditPartForm(HelperForm): class EditPartForm(HelperForm):
""" Form for editing a Part object """ """ Form for editing a Part object """

View File

@ -49,6 +49,7 @@
<div class='dropdown' style='float: right;'> <div class='dropdown' style='float: right;'>
<button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">Options<span class='caret'></span></button> <button id='part-options' class='btn btn-primary dropdown-toggle' type='button' data-toggle="dropdown">Options<span class='caret'></span></button>
<ul class='dropdown-menu'> <ul class='dropdown-menu'>
<li><a href='#' id='multi-part-category' title='Set category'>Set Category</a></li>
<li><a href='#' id='multi-part-order' title='Order parts'>Order Parts</a></li> <li><a href='#' id='multi-part-order' title='Order parts'>Order Parts</a></li>
<li><a href='#' id='multi-part-export' title='Export'>Export Data</a></li> <li><a href='#' id='multi-part-export' title='Export'>Export Data</a></li>
</ul> </ul>

View File

@ -10,7 +10,7 @@
<div id='button-bar'> <div id='button-bar'>
<div class='btn-group'> <div class='btn-group'>
<button class='btn btn-primary' type='button' id='part-order-2' title='Order part'>Order Part</button> <button class='btn btn-primary' type='button' id='part-order2' title='Order part'>Order Part</button>
</div> </div>
</div> </div>
@ -31,11 +31,12 @@ $("#po-table").bootstrapTable({
sortable: true, sortable: true,
}); });
$("#part-order-2").click(function() { $("#part-order2").click(function() {
launchModalForm("/order/purchase-order/order-parts/", { launchModalForm("{% url 'order-parts' %}", {
data: { data: {
part: {{ part.id }}, part: {{ part.id }},
}, },
reload: true,
}); });
}); });

View File

@ -184,8 +184,8 @@
data: { data: {
action: "count", action: "count",
part: {{ part.id }}, part: {{ part.id }},
reload: true, },
} reload: true,
}); });
}); });
@ -225,10 +225,10 @@
}); });
$("#part-order").click(function() { $("#part-order").click(function() {
launchModalForm("/order/purchase-order/order-parts/", { launchModalForm("{% url 'order-parts' %}", {
data: { data: {
part: {{ part.id }}, part: {{ part.id }},
}, }
}); });
}); });

View File

@ -2,57 +2,41 @@
{% block form %} {% block form %}
<form method="post" action='' class='js-modal-form' enctype="multipart/form-data"> <form method="post" action='' class='js-modal-form' enctype="multipart/form-data">
{% csrf_token %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
<div class='control-group'>
<label class='control-label requiredField'>Location</label>
<div class='controls'>
<select class='select' name='part_category'>
<option value=''>---------</option>
{% for cat in categories %}
<option value='{{ cat.id }}' {% if category and category.id == cat.id %}selected='selected'{% endif %}>{{ cat.pathstring }} - {{ cat.description }}</option>
{% endfor %}
</select>
{% if category %}
<p class='help-block'>Select Part Category</p>
{% else %}
<p class='help-inline'>Select Part Category</p>
{% endif %}
</div>
</div>
<label class='control-label'>Parts</label> <label class='control-label'>Parts</label>
<p class='help-block'>Set category for the following parts</p> <p class='help-block'>Set category for the following parts</p>
<table class='table table-striped'> <table class='table table-striped'>
<tr> <tr>
<th>Part</th> <th>Part</th>
<th>Description</th> <th>Description</th>
<th>Category</th> <th>Category</th>
<th> <th>
</tr> </tr>
{% for part in parts %} {% for part in parts %}
<tr id='part_row_{{ part.id }}'> <tr id='part_row_{{ part.id }}'>
<input type='hidden' name='part_id_{{ part.id }}' value='1'/> <input type='hidden' name='part_id_{{ part.id }}' value='1'/>
<td> <td>
{% include "hover_image.html" with image=part.image hover=False %} {% include "hover_image.html" with image=part.image hover=False %}
{{ part.full_name }} {{ part.full_name }}
</td> </td>
<td> <td>
{{ part.description }} {{ part.description }}
</td> </td>
<td> <td>
{{ part.category.pathstring }} {{ part.category.pathstring }}
</td> </td>
<td> <td>
<button class='btn btn-default btn-remove' onClick='removeRowFromModalForm()' title='Remove part' type='button'> <button class='btn btn-default btn-remove' onClick='removeRowFromModalForm()' title='Remove part' type='button'>
<span row='part_row_{{ part.id }}' class='glyphicon glyphicon-small glyphicon-remove'></span> <span row='part_row_{{ part.id }}' class='glyphicon glyphicon-small glyphicon-remove'></span>
</button> </button>
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
</form> {% crispy form %}
{% endblock %}
</form>
{% endblock %}

View File

@ -46,6 +46,12 @@ def inventree_commit(*args, **kwargs):
@register.simple_tag() @register.simple_tag()
def inventree_github(*args, **kwargs): def inventree_github_url(*args, **kwargs):
""" Return URL for InvenTree github site """ """ Return URL for InvenTree github site """
return "https://github.com/InvenTree" return "https://github.com/InvenTree"
@register.simple_tag()
def inventree_docs_url(*args, **kwargs):
""" Return URL for InvenTree documenation site """
return "https://inventree.github.io"

View File

@ -26,7 +26,10 @@ class TemplateTagTest(TestCase):
self.assertEqual(len(hash), 7) self.assertEqual(len(hash), 7)
def test_github(self): def test_github(self):
self.assertIn('github.com', inventree_extras.inventree_github()) self.assertIn('github.com', inventree_extras.inventree_github_url())
def test_docs(self):
self.assertIn('inventree.github.io', inventree_extras.inventree_docs_url())
class PartTest(TestCase): class PartTest(TestCase):

View File

@ -6,6 +6,7 @@ Django views for interacting with Part app
from __future__ import unicode_literals from __future__ import unicode_literals
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.shortcuts import HttpResponseRedirect from django.shortcuts import HttpResponseRedirect
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -138,11 +139,12 @@ class PartAttachmentDelete(AjaxDeleteView):
} }
class PartSetCategory(AjaxView): class PartSetCategory(AjaxUpdateView):
""" View for settings the part category for multiple parts at once """ """ View for settings the part category for multiple parts at once """
ajax_template_name = 'part/set_category.html' ajax_template_name = 'part/set_category.html'
ajax_form_title = 'Set Part Category' ajax_form_title = 'Set Part Category'
form_class = part_forms.SetPartCategoryForm
category = None category = None
parts = [] parts = []
@ -157,7 +159,7 @@ class PartSetCategory(AjaxView):
else: else:
self.parts = [] self.parts = []
return self.renderJsonResponse(request, context=self.get_context_data()) return self.renderJsonResponse(request, form=self.get_form(), context=self.get_context_data())
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
""" Respond to a POST request to this view """ """ Respond to a POST request to this view """
@ -193,10 +195,14 @@ class PartSetCategory(AjaxView):
} }
if valid: if valid:
for part in self.parts: self.set_category()
part.set_category(self.category)
return self.renderJsonResponse(request, data=data, context=self.get_context_data()) return self.renderJsonResponse(request, data=data, form=self.get_form(), context=self.get_context_data())
@transaction.atomic
def set_category(self):
for part in self.parts:
part.set_category(self.category)
def get_context_data(self): def get_context_data(self):
""" Return context data for rendering in the form """ """ Return context data for rendering in the form """

View File

@ -26,7 +26,11 @@
<td colspan="2"></td> <td colspan="2"></td>
</tr> </tr>
<tr> <tr>
<td>View Code on GitHub</td><td><a href="{% inventree_github %}">{% inventree_github %}</a></td> <td>InvenTree Documenation</td>
<td><a href="{% inventree_docs_url %}">{% inventree_docs_url %}</a></td>
</tr>
<tr>
<td>View Code on GitHub</td><td><a href="{% inventree_github_url %}">{% inventree_github_url %}</a></td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>