mirror of
https://github.com/inventree/InvenTree.git
synced 2026-05-09 03:03:41 +00:00
Merge branch 'inventree:master' into matmair/issue2201
This commit is contained in:
@@ -46,7 +46,7 @@ class InvenTreeAPITestCase(APITestCase):
|
||||
self.user.is_staff = True
|
||||
|
||||
self.user.save()
|
||||
|
||||
|
||||
for role in self.roles:
|
||||
self.assignRole(role)
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
"""
|
||||
Pull rendered copies of the templated
|
||||
Pull rendered copies of the templated
|
||||
"""
|
||||
|
||||
from django.http import response
|
||||
from django.test import TestCase, testcases
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
import os
|
||||
|
||||
@@ -53,7 +53,7 @@ class InvenTreeModelMoneyField(ModelMoneyField):
|
||||
"""
|
||||
Custom MoneyField for clean migrations while using dynamic currency settings
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
# detect if creating migration
|
||||
if 'migrate' in sys.argv or 'makemigrations' in sys.argv:
|
||||
|
||||
@@ -38,7 +38,7 @@ class InvenTreeOrderingFilter(OrderingFilter):
|
||||
ordering = []
|
||||
|
||||
for field in ordering_initial:
|
||||
|
||||
|
||||
reverse = field.startswith('-')
|
||||
|
||||
if reverse:
|
||||
@@ -52,7 +52,7 @@ class InvenTreeOrderingFilter(OrderingFilter):
|
||||
|
||||
"""
|
||||
Potentially, a single field could be "aliased" to multiple field,
|
||||
|
||||
|
||||
(For example to enforce a particular ordering sequence)
|
||||
|
||||
e.g. to filter first by the integer value...
|
||||
|
||||
@@ -36,7 +36,7 @@ class Command(BaseCommand):
|
||||
img = model.image
|
||||
url = img.thumbnail.name
|
||||
loc = os.path.join(settings.MEDIA_ROOT, url)
|
||||
|
||||
|
||||
if not os.path.exists(loc):
|
||||
logger.info(f"Generating thumbnail image for '{img}'")
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
"""
|
||||
|
||||
def determine_metadata(self, request, view):
|
||||
|
||||
|
||||
self.request = request
|
||||
self.view = view
|
||||
|
||||
@@ -98,7 +98,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
Override get_serializer_info so that we can add 'default' values
|
||||
to any fields whose Meta.model specifies a default value
|
||||
"""
|
||||
|
||||
|
||||
serializer_info = super().get_serializer_info(serializer)
|
||||
|
||||
model_class = None
|
||||
@@ -174,7 +174,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
# Extract extra information if an instance is available
|
||||
if hasattr(serializer, 'instance'):
|
||||
instance = serializer.instance
|
||||
|
||||
|
||||
if instance is None and model_class is not None:
|
||||
# Attempt to find the instance based on kwargs lookup
|
||||
kwargs = getattr(self.view, 'kwargs', None)
|
||||
@@ -240,7 +240,7 @@ class InvenTreeMetadata(SimpleMetadata):
|
||||
|
||||
# Introspect writable related fields
|
||||
if field_info['type'] == 'field' and not field_info['read_only']:
|
||||
|
||||
|
||||
# If the field is a PrimaryKeyRelatedField, we can extract the model from the queryset
|
||||
if isinstance(field, serializers.PrimaryKeyRelatedField):
|
||||
model = field.queryset.model
|
||||
|
||||
@@ -66,7 +66,7 @@ class InvenTreeMoneySerializer(MoneyField):
|
||||
|
||||
if currency and amount is not None and not isinstance(amount, MONEY_CLASSES) and amount is not empty:
|
||||
return Money(amount, currency)
|
||||
|
||||
|
||||
return amount
|
||||
|
||||
|
||||
|
||||
@@ -673,7 +673,7 @@ LANGUAGES = [
|
||||
('el', _('Greek')),
|
||||
('en', _('English')),
|
||||
('es', _('Spanish')),
|
||||
('es-mx', _('Spanish (Mexican')),
|
||||
('es-mx', _('Spanish (Mexican)')),
|
||||
('fr', _('French')),
|
||||
('he', _('Hebrew')),
|
||||
('it', _('Italian')),
|
||||
|
||||
@@ -106,7 +106,7 @@ def offload_task(taskname, *args, force_sync=False, **kwargs):
|
||||
except NameError:
|
||||
logger.warning(f"WARNING: '{taskname}' not started - No function named '{func}'")
|
||||
return
|
||||
|
||||
|
||||
# Workers are not running: run it as synchronous task
|
||||
_func(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ from base64 import b64encode
|
||||
class HTMLAPITests(TestCase):
|
||||
"""
|
||||
Test that we can access the REST API endpoints via the HTML interface.
|
||||
|
||||
|
||||
History: Discovered on 2021-06-28 a bug in InvenTreeModelSerializer,
|
||||
which raised an AssertionError when using the HTML API interface,
|
||||
while the regular JSON interface continued to work as expected.
|
||||
@@ -280,7 +280,7 @@ class APITests(InvenTreeAPITestCase):
|
||||
"""
|
||||
Tests for detail API endpoint actions
|
||||
"""
|
||||
|
||||
|
||||
self.basicAuth()
|
||||
|
||||
url = reverse('api-part-detail', kwargs={'pk': 1})
|
||||
|
||||
@@ -77,7 +77,7 @@ apipatterns = [
|
||||
settings_urls = [
|
||||
|
||||
url(r'^i18n/?', include('django.conf.urls.i18n')),
|
||||
|
||||
|
||||
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
|
||||
url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
|
||||
|
||||
|
||||
@@ -120,10 +120,10 @@ def isInvenTreeDevelopmentVersion():
|
||||
def inventreeDocsVersion():
|
||||
"""
|
||||
Return the version string matching the latest documentation.
|
||||
|
||||
|
||||
Development -> "latest"
|
||||
Release -> "major.minor.sub" e.g. "0.5.2"
|
||||
|
||||
|
||||
"""
|
||||
|
||||
if isInvenTreeDevelopmentVersion():
|
||||
|
||||
@@ -198,7 +198,7 @@ class BuildUnallocate(generics.CreateAPIView):
|
||||
queryset = Build.objects.none()
|
||||
|
||||
serializer_class = BuildUnallocationSerializer
|
||||
|
||||
|
||||
def get_serializer_context(self):
|
||||
|
||||
ctx = super().get_serializer_context()
|
||||
@@ -231,7 +231,7 @@ class BuildComplete(generics.CreateAPIView):
|
||||
ctx['build'] = Build.objects.get(pk=self.kwargs.get('pk', None))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ class BuildItemList(generics.ListCreateAPIView):
|
||||
kwargs['location_detail'] = str2bool(params.get('location_detail', False))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
return self.serializer_class(*args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
|
||||
@@ -66,7 +66,7 @@ def get_next_build_number():
|
||||
attempts.add(reference)
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
return reference
|
||||
|
||||
|
||||
@@ -94,13 +94,13 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
"""
|
||||
|
||||
OVERDUE_FILTER = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__lte=datetime.now().date())
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
return reverse('api-build-list')
|
||||
|
||||
def api_instance_filters(self):
|
||||
|
||||
|
||||
return {
|
||||
'parent': {
|
||||
'exclude_tree': self.pk,
|
||||
@@ -1178,7 +1178,7 @@ class BuildItem(models.Model):
|
||||
bom_item = PartModels.BomItem.objects.get(part=self.build.part, sub_part=ancestor)
|
||||
except PartModels.BomItem.DoesNotExist:
|
||||
continue
|
||||
|
||||
|
||||
# A matching BOM item has been found!
|
||||
if idx == 0 or bom_item.allow_variants:
|
||||
bom_item_valid = True
|
||||
@@ -1234,7 +1234,7 @@ class BuildItem(models.Model):
|
||||
thumb_url = self.stock_item.part.image.thumbnail.url
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if thumb_url is None and self.bom_item and self.bom_item.sub_part:
|
||||
try:
|
||||
thumb_url = self.bom_item.sub_part.image.thumbnail.url
|
||||
|
||||
@@ -309,7 +309,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
|
||||
)
|
||||
|
||||
def validate_bom_item(self, bom_item):
|
||||
|
||||
|
||||
# TODO: Fix this validation - allow for variants and substitutes!
|
||||
|
||||
build = self.context['build']
|
||||
@@ -332,7 +332,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
|
||||
|
||||
if not stock_item.in_stock:
|
||||
raise ValidationError(_("Item must be in stock"))
|
||||
|
||||
|
||||
return stock_item
|
||||
|
||||
quantity = serializers.DecimalField(
|
||||
@@ -398,7 +398,7 @@ class BuildAllocationItemSerializer(serializers.Serializer):
|
||||
|
||||
# Output *cannot* be set for un-tracked parts
|
||||
if output is not None and not bom_item.sub_part.trackable:
|
||||
|
||||
|
||||
raise ValidationError({
|
||||
'output': _('Build output cannot be specified for allocation of untracked parts')
|
||||
})
|
||||
@@ -422,14 +422,14 @@ class BuildAllocationSerializer(serializers.Serializer):
|
||||
"""
|
||||
Validation
|
||||
"""
|
||||
|
||||
|
||||
super().validate(data)
|
||||
|
||||
items = data.get('items', [])
|
||||
|
||||
if len(items) == 0:
|
||||
raise ValidationError(_('Allocation items must be provided'))
|
||||
|
||||
|
||||
return data
|
||||
|
||||
def save(self):
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='details' text="Build Order Details" icon="fa-info-circle" %}
|
||||
{% trans "Build Order Details" as text %}
|
||||
{% include "sidebar_item.html" with label='details' text=text icon="fa-info-circle" %}
|
||||
{% if build.active %}
|
||||
{% include "sidebar_item.html" with label='allocate' text="Allocate Stock" icon="fa-tasks" %}
|
||||
{% trans "Allocate Stock" as text %}
|
||||
{% include "sidebar_item.html" with label='allocate' text=text icon="fa-tasks" %}
|
||||
{% endif %}
|
||||
{% if not build.is_complete %}
|
||||
{% include "sidebar_item.html" with label='outputs' text="Pending Items" icon="fa-tools" %}
|
||||
{% trans "Pending Items" as text %}
|
||||
{% include "sidebar_item.html" with label='outputs' text=text icon="fa-tools" %}
|
||||
{% endif %}
|
||||
{% include "sidebar_item.html" with label='completed' text="Completed Items" icon="fa-boxes" %}
|
||||
{% include "sidebar_item.html" with label='children' text="Child Build Orders" icon="fa-sitemap" %}
|
||||
{% include "sidebar_item.html" with label='attachments' text="Attachments" icon="fa-paperclip" %}
|
||||
{% include "sidebar_item.html" with label='notes' text="Notes" icon="fa-clipboard" %}
|
||||
{% trans "Completed Items" as text %}
|
||||
{% include "sidebar_item.html" with label='completed' text=text icon="fa-boxes" %}
|
||||
{% trans "Child Build Orders" as text %}
|
||||
{% include "sidebar_item.html" with label='children' text=text icon="fa-sitemap" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label='attachments' text=text icon="fa-paperclip" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label='notes' text=text icon="fa-clipboard" %}
|
||||
|
||||
@@ -73,7 +73,7 @@ class GlobalSettingsDetail(generics.RetrieveUpdateAPIView):
|
||||
permission_classes = [
|
||||
GlobalSettingsPermissions,
|
||||
]
|
||||
|
||||
|
||||
|
||||
class UserSettingsList(SettingsList):
|
||||
"""
|
||||
@@ -124,7 +124,7 @@ class UserSettingsDetail(generics.RetrieveUpdateAPIView):
|
||||
|
||||
queryset = common.models.InvenTreeUserSetting.objects.all()
|
||||
serializer_class = common.serializers.UserSettingsSerializer
|
||||
|
||||
|
||||
permission_classes = [
|
||||
UserSettingsPermissions,
|
||||
]
|
||||
|
||||
@@ -12,7 +12,7 @@ class CommonConfig(AppConfig):
|
||||
name = 'common'
|
||||
|
||||
def ready(self):
|
||||
|
||||
|
||||
self.clear_restart_flag()
|
||||
|
||||
def clear_restart_flag(self):
|
||||
@@ -22,7 +22,7 @@ class CommonConfig(AppConfig):
|
||||
|
||||
try:
|
||||
import common.models
|
||||
|
||||
|
||||
if common.models.InvenTreeSetting.get_setting('SERVER_RESTART_REQUIRED'):
|
||||
logger.info("Clearing SERVER_RESTART_REQUIRED flag")
|
||||
common.models.InvenTreeSetting.set_setting('SERVER_RESTART_REQUIRED', False, None)
|
||||
|
||||
@@ -108,7 +108,9 @@ class BaseInvenTreeSetting(models.Model):
|
||||
for key, value in settings.items():
|
||||
validator = cls.get_setting_validator(key)
|
||||
|
||||
if cls.validator_is_bool(validator):
|
||||
if cls.is_protected(key):
|
||||
value = '***'
|
||||
elif cls.validator_is_bool(validator):
|
||||
value = InvenTree.helpers.str2bool(value)
|
||||
elif cls.validator_is_int(validator):
|
||||
try:
|
||||
@@ -485,7 +487,7 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
elif self.is_int():
|
||||
return 'integer'
|
||||
|
||||
|
||||
else:
|
||||
return 'string'
|
||||
|
||||
@@ -538,6 +540,19 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def is_protected(cls, key):
|
||||
"""
|
||||
Check if the setting value is protected
|
||||
"""
|
||||
|
||||
key = str(key).strip().upper()
|
||||
|
||||
if key in cls.GLOBAL_SETTINGS:
|
||||
return cls.GLOBAL_SETTINGS[key].get('protected', False)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def settings_group_options():
|
||||
"""build up group tuple for settings based on gour choices"""
|
||||
|
||||
@@ -45,6 +45,18 @@ class SettingsSerializer(InvenTreeModelSerializer):
|
||||
|
||||
return results
|
||||
|
||||
def get_value(self, obj):
|
||||
"""
|
||||
Make sure protected values are not returned
|
||||
"""
|
||||
result = obj.value
|
||||
|
||||
# never return protected values
|
||||
if obj.is_protected:
|
||||
result = '***'
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class GlobalSettingsSerializer(SettingsSerializer):
|
||||
"""
|
||||
|
||||
@@ -170,7 +170,7 @@ class ManufacturerPartParameterList(generics.ListCreateAPIView):
|
||||
|
||||
queryset = ManufacturerPartParameter.objects.all()
|
||||
serializer_class = ManufacturerPartParameterSerializer
|
||||
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
|
||||
# Do we wish to include any extra detail?
|
||||
|
||||
@@ -477,7 +477,7 @@ class SupplierPart(models.Model):
|
||||
return reverse('supplier-part-detail', kwargs={'pk': self.id})
|
||||
|
||||
def api_instance_filters(self):
|
||||
|
||||
|
||||
return {
|
||||
'manufacturer_part': {
|
||||
'part': self.part.pk
|
||||
|
||||
@@ -187,7 +187,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||
part_detail = kwargs.pop('part_detail', True)
|
||||
supplier_detail = kwargs.pop('supplier_detail', True)
|
||||
manufacturer_detail = kwargs.pop('manufacturer_detail', True)
|
||||
|
||||
|
||||
prettify = kwargs.pop('pretty', False)
|
||||
|
||||
super(SupplierPartSerializer, self).__init__(*args, **kwargs)
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='parameters' text="Parameters" icon="fa-th-list" %}
|
||||
{% include "sidebar_item.html" with label='supplier-parts' text="Supplier Parts" icon="fa-building" %}
|
||||
{% trans "Parameters" as text %}
|
||||
{% include "sidebar_item.html" with label='parameters' text=text icon="fa-th-list" %}
|
||||
{% trans "Supplier Parts" as text %}
|
||||
{% include "sidebar_item.html" with label='supplier-parts' text=text icon="fa-building" %}
|
||||
@@ -3,17 +3,24 @@
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% if company.is_manufacturer %}
|
||||
{% include "sidebar_item.html" with label='manufacturer-parts' text="Manufactured Parts" icon="fa-industry" %}
|
||||
{% trans "Manufactured Parts" as text %}
|
||||
{% include "sidebar_item.html" with label='manufacturer-parts' text=text icon="fa-industry" %}
|
||||
{% endif %}
|
||||
{% if company.is_supplier %}
|
||||
{% include "sidebar_item.html" with label='supplier-parts' text="Supplied Parts" icon="fa-building" %}
|
||||
{% include "sidebar_item.html" with label='purchase-orders' text="Purchase Orders" icon="fa-shopping-cart" %}
|
||||
{% trans "Supplied Parts" as text %}
|
||||
{% include "sidebar_item.html" with label='supplier-parts' text=text icon="fa-building" %}
|
||||
{% trans "Purchase Orders" as text %}
|
||||
{% include "sidebar_item.html" with label='purchase-orders' text=text icon="fa-shopping-cart" %}
|
||||
{% endif %}
|
||||
{% if company.is_manufacturer or company.is_supplier %}
|
||||
{% include "sidebar_item.html" with label='company-stock' text="Supplied Stock Items" icon="fa-boxes" %}
|
||||
{% trans "Supplied Stock Items" as text %}
|
||||
{% include "sidebar_item.html" with label='company-stock' text=text icon="fa-boxes" %}
|
||||
{% endif %}
|
||||
{% if company.is_customer %}
|
||||
{% include "sidebar_item.html" with label='sales-orders' text="Sales Orders" icon="fa-truck" %}
|
||||
{% include "sidebar_item.html" with label='assigned-stock' text="Assigned Stock Items" icon="fa-sign-out-alt" %}
|
||||
{% trans "Sales Orders" as text %}
|
||||
{% include "sidebar_item.html" with label='sales-orders' text=text icon="fa-truck" %}
|
||||
{% trans "Assigned Stock Items" as text %}
|
||||
{% include "sidebar_item.html" with label='assigned-stock' text=text icon="fa-sign-out-alt" %}
|
||||
{% endif %}
|
||||
{% include "sidebar_item.html" with label='company-notes' text="Notes" icon="fa-clipboard" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label='company-notes' text=text icon="fa-clipboard" %}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='stock' text="Stock Items" icon="fa-boxes" %}
|
||||
{% include "sidebar_item.html" with label='purchase-orders' text="Purchase Orders" icon="fa-shopping-cart" %}
|
||||
{% include "sidebar_item.html" with label='pricing' text="Supplier Part Pricing" icon="fa-dollar-sign" %}
|
||||
{% trans "Stock Items" as text %}
|
||||
{% include "sidebar_item.html" with label='stock' text=text icon="fa-boxes" %}
|
||||
{% trans "Purchase Orders" as text %}
|
||||
{% include "sidebar_item.html" with label='purchase-orders' text=text icon="fa-shopping-cart" %}
|
||||
{% trans "Supplier Part Pricing" as text %}
|
||||
{% include "sidebar_item.html" with label='pricing' text=text icon="fa-dollar-sign" %}
|
||||
|
||||
@@ -202,7 +202,7 @@ class ManufacturerTest(InvenTreeAPITestCase):
|
||||
data = {
|
||||
'MPN': 'MPN-TEST-123',
|
||||
}
|
||||
|
||||
|
||||
response = self.client.patch(url, data, format='json')
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
@@ -29,7 +29,7 @@ company_urls = [
|
||||
]
|
||||
|
||||
manufacturer_part_urls = [
|
||||
|
||||
|
||||
url(r'^(?P<pk>\d+)/', views.ManufacturerPartDetail.as_view(template_name='company/manufacturer_part.html'), name='manufacturer-part-detail'),
|
||||
]
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ class PartLabelMixin:
|
||||
if key in params:
|
||||
parts = params.getlist(key, [])
|
||||
break
|
||||
|
||||
|
||||
valid_ids = []
|
||||
|
||||
for part in parts:
|
||||
|
||||
@@ -186,7 +186,7 @@ class LabelTemplate(models.Model):
|
||||
"""
|
||||
|
||||
template_string = Template(self.filename_pattern)
|
||||
|
||||
|
||||
ctx = self.context(request)
|
||||
|
||||
context = Context(ctx)
|
||||
|
||||
Binary file not shown.
+3366
-2794
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
+3291
-3123
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2966
-2845
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-19 07:42+1100\n"
|
||||
"POT-Creation-Date: 2021-11-22 22:08+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -131,8 +131,8 @@ msgstr ""
|
||||
msgid "File comment"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/models.py:118 InvenTree/models.py:119 common/models.py:1170
|
||||
#: common/models.py:1171 part/models.py:2205 part/models.py:2225
|
||||
#: InvenTree/models.py:118 InvenTree/models.py:119 common/models.py:1185
|
||||
#: common/models.py:1186 part/models.py:2205 part/models.py:2225
|
||||
#: report/templates/report/inventree_test_report_base.html:96
|
||||
#: templates/js/translated/stock.js:2054
|
||||
msgid "User"
|
||||
@@ -234,7 +234,7 @@ msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/settings.py:667
|
||||
msgid "Spanish (Mexican"
|
||||
msgid "Spanish (Mexican)"
|
||||
msgstr ""
|
||||
|
||||
#: InvenTree/settings.py:668
|
||||
@@ -544,7 +544,7 @@ msgstr ""
|
||||
|
||||
#: build/forms.py:36 build/models.py:1283
|
||||
#: build/templates/build/build_base.html:124
|
||||
#: build/templates/build/detail.html:35 common/models.py:1210
|
||||
#: build/templates/build/detail.html:35 common/models.py:1225
|
||||
#: company/forms.py:42 company/templates/company/supplier_part.html:251
|
||||
#: order/forms.py:102 order/models.py:729 order/models.py:991
|
||||
#: order/templates/order/order_wizard/match_parts.html:30
|
||||
@@ -1454,688 +1454,688 @@ msgstr ""
|
||||
msgid "Select {name} file to upload"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:338 common/models.py:955 common/models.py:1163
|
||||
#: common/models.py:340 common/models.py:970 common/models.py:1178
|
||||
msgid "Settings key (must be unique - case insensitive"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:340
|
||||
#: common/models.py:342
|
||||
msgid "Settings value"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:375
|
||||
#: common/models.py:377
|
||||
msgid "Must be an integer value"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:380
|
||||
#: common/models.py:382
|
||||
msgid "Chosen value is not a valid option"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:403
|
||||
#: common/models.py:405
|
||||
msgid "Value must be a boolean value"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:414
|
||||
#: common/models.py:416
|
||||
msgid "Value must be an integer value"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:437
|
||||
#: common/models.py:439
|
||||
msgid "Key string must be unique"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:544
|
||||
#: common/models.py:559
|
||||
msgid "No group"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:586
|
||||
#: common/models.py:601
|
||||
msgid "Restart required"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:587
|
||||
#: common/models.py:602
|
||||
msgid "A setting has been changed which requires a server restart"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:594
|
||||
#: common/models.py:609
|
||||
msgid "InvenTree Instance Name"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:596
|
||||
#: common/models.py:611
|
||||
msgid "String descriptor for the server instance"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:600
|
||||
#: common/models.py:615
|
||||
msgid "Use instance name"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:601
|
||||
#: common/models.py:616
|
||||
msgid "Use the instance name in the title-bar"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:607 company/models.py:100 company/models.py:101
|
||||
#: common/models.py:622 company/models.py:100 company/models.py:101
|
||||
msgid "Company name"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:608
|
||||
#: common/models.py:623
|
||||
msgid "Internal company name"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:613
|
||||
#: common/models.py:628
|
||||
msgid "Base URL"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:614
|
||||
#: common/models.py:629
|
||||
msgid "Base URL for server instance"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:620
|
||||
#: common/models.py:635
|
||||
msgid "Default Currency"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:621
|
||||
#: common/models.py:636
|
||||
msgid "Default currency"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:627
|
||||
#: common/models.py:642
|
||||
msgid "Download from URL"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:628
|
||||
#: common/models.py:643
|
||||
msgid "Allow download of remote images and files from external URL"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:634
|
||||
#: common/models.py:649
|
||||
msgid "Barcode Support"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:635
|
||||
#: common/models.py:650
|
||||
msgid "Enable barcode scanner support"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:641
|
||||
#: common/models.py:656
|
||||
msgid "IPN Regex"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:642
|
||||
#: common/models.py:657
|
||||
msgid "Regular expression pattern for matching Part IPN"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:646
|
||||
#: common/models.py:661
|
||||
msgid "Allow Duplicate IPN"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:647
|
||||
#: common/models.py:662
|
||||
msgid "Allow multiple parts to share the same IPN"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:653
|
||||
#: common/models.py:668
|
||||
msgid "Allow Editing IPN"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:654
|
||||
#: common/models.py:669
|
||||
msgid "Allow changing the IPN value while editing a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:660
|
||||
#: common/models.py:675
|
||||
msgid "Copy Part BOM Data"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:661
|
||||
#: common/models.py:676
|
||||
msgid "Copy BOM data by default when duplicating a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:667
|
||||
#: common/models.py:682
|
||||
msgid "Copy Part Parameter Data"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:668
|
||||
#: common/models.py:683
|
||||
msgid "Copy parameter data by default when duplicating a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:674
|
||||
#: common/models.py:689
|
||||
msgid "Copy Part Test Data"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:675
|
||||
#: common/models.py:690
|
||||
msgid "Copy test data by default when duplicating a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:681
|
||||
#: common/models.py:696
|
||||
msgid "Copy Category Parameter Templates"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:682
|
||||
#: common/models.py:697
|
||||
msgid "Copy category parameter templates when creating a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:688 part/models.py:2429 report/models.py:187
|
||||
#: common/models.py:703 part/models.py:2429 report/models.py:187
|
||||
#: templates/js/translated/table_filters.js:38
|
||||
#: templates/js/translated/table_filters.js:367
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:689
|
||||
#: common/models.py:704
|
||||
msgid "Parts are templates by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:695 part/models.py:888 templates/js/translated/bom.js:954
|
||||
#: common/models.py:710 part/models.py:888 templates/js/translated/bom.js:954
|
||||
#: templates/js/translated/table_filters.js:162
|
||||
#: templates/js/translated/table_filters.js:379
|
||||
msgid "Assembly"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:696
|
||||
#: common/models.py:711
|
||||
msgid "Parts can be assembled from other components by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:702 part/models.py:894
|
||||
#: common/models.py:717 part/models.py:894
|
||||
#: templates/js/translated/table_filters.js:383
|
||||
msgid "Component"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:703
|
||||
#: common/models.py:718
|
||||
msgid "Parts can be used as sub-components by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:709 part/models.py:905
|
||||
#: common/models.py:724 part/models.py:905
|
||||
msgid "Purchaseable"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:710
|
||||
#: common/models.py:725
|
||||
msgid "Parts are purchaseable by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:716 part/models.py:910
|
||||
#: common/models.py:731 part/models.py:910
|
||||
#: templates/js/translated/table_filters.js:391
|
||||
msgid "Salable"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:717
|
||||
#: common/models.py:732
|
||||
msgid "Parts are salable by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:723 part/models.py:900
|
||||
#: common/models.py:738 part/models.py:900
|
||||
#: templates/js/translated/table_filters.js:46
|
||||
#: templates/js/translated/table_filters.js:94
|
||||
#: templates/js/translated/table_filters.js:395
|
||||
msgid "Trackable"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:724
|
||||
#: common/models.py:739
|
||||
msgid "Parts are trackable by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:730 part/models.py:920
|
||||
#: common/models.py:745 part/models.py:920
|
||||
#: part/templates/part/part_base.html:144
|
||||
#: templates/js/translated/table_filters.js:42
|
||||
msgid "Virtual"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:731
|
||||
#: common/models.py:746
|
||||
msgid "Parts are virtual by default"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:737
|
||||
#: common/models.py:752
|
||||
msgid "Show Import in Views"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:738
|
||||
#: common/models.py:753
|
||||
msgid "Display the import wizard in some part views"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:744
|
||||
#: common/models.py:759
|
||||
msgid "Show Price in Forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:745
|
||||
#: common/models.py:760
|
||||
msgid "Display part price in some forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:756
|
||||
#: common/models.py:771
|
||||
msgid "Show Price in BOM"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:757
|
||||
#: common/models.py:772
|
||||
msgid "Include pricing information in BOM tables"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:763
|
||||
#: common/models.py:778
|
||||
msgid "Show related parts"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:764
|
||||
#: common/models.py:779
|
||||
msgid "Display related parts for a part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:770
|
||||
#: common/models.py:785
|
||||
msgid "Create initial stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:771
|
||||
#: common/models.py:786
|
||||
msgid "Create initial stock on part creation"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:777
|
||||
#: common/models.py:792
|
||||
msgid "Internal Prices"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:778
|
||||
#: common/models.py:793
|
||||
msgid "Enable internal prices for parts"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:784
|
||||
#: common/models.py:799
|
||||
msgid "Internal Price as BOM-Price"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:785
|
||||
#: common/models.py:800
|
||||
msgid "Use the internal price (if set) in BOM-price calculations"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:791
|
||||
#: common/models.py:806
|
||||
msgid "Part Name Display Format"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:792
|
||||
#: common/models.py:807
|
||||
msgid "Format to display the part name"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:799
|
||||
#: common/models.py:814
|
||||
msgid "Enable Reports"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:800
|
||||
#: common/models.py:815
|
||||
msgid "Enable generation of reports"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:806 templates/stats.html:25
|
||||
#: common/models.py:821 templates/stats.html:25
|
||||
msgid "Debug Mode"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:807
|
||||
#: common/models.py:822
|
||||
msgid "Generate reports in debug mode (HTML output)"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:813
|
||||
#: common/models.py:828
|
||||
msgid "Page Size"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:814
|
||||
#: common/models.py:829
|
||||
msgid "Default page size for PDF reports"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:824
|
||||
#: common/models.py:839
|
||||
msgid "Test Reports"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:825
|
||||
#: common/models.py:840
|
||||
msgid "Enable generation of test reports"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:831
|
||||
#: common/models.py:846
|
||||
msgid "Stock Expiry"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:832
|
||||
#: common/models.py:847
|
||||
msgid "Enable stock expiry functionality"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:838
|
||||
#: common/models.py:853
|
||||
msgid "Sell Expired Stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:839
|
||||
#: common/models.py:854
|
||||
msgid "Allow sale of expired stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:845
|
||||
#: common/models.py:860
|
||||
msgid "Stock Stale Time"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:846
|
||||
#: common/models.py:861
|
||||
msgid "Number of days stock items are considered stale before expiring"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:848
|
||||
#: common/models.py:863
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:853
|
||||
#: common/models.py:868
|
||||
msgid "Build Expired Stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:854
|
||||
#: common/models.py:869
|
||||
msgid "Allow building with expired stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:860
|
||||
#: common/models.py:875
|
||||
msgid "Stock Ownership Control"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:861
|
||||
#: common/models.py:876
|
||||
msgid "Enable ownership control over stock locations and items"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:867
|
||||
#: common/models.py:882
|
||||
msgid "Group by Part"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:868
|
||||
#: common/models.py:883
|
||||
msgid "Group stock items by part reference in table views"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:874
|
||||
#: common/models.py:889
|
||||
msgid "Build Order Reference Prefix"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:875
|
||||
#: common/models.py:890
|
||||
msgid "Prefix value for build order reference"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:880
|
||||
#: common/models.py:895
|
||||
msgid "Build Order Reference Regex"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:881
|
||||
#: common/models.py:896
|
||||
msgid "Regular expression pattern for matching build order reference"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:885
|
||||
#: common/models.py:900
|
||||
msgid "Sales Order Reference Prefix"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:886
|
||||
#: common/models.py:901
|
||||
msgid "Prefix value for sales order reference"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:891
|
||||
#: common/models.py:906
|
||||
msgid "Purchase Order Reference Prefix"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:892
|
||||
#: common/models.py:907
|
||||
msgid "Prefix value for purchase order reference"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:898
|
||||
#: common/models.py:913
|
||||
msgid "Enable password forgot"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:899
|
||||
#: common/models.py:914
|
||||
msgid "Enable password forgot function on the login pages"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:904
|
||||
#: common/models.py:919
|
||||
msgid "Enable registration"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:905
|
||||
#: common/models.py:920
|
||||
msgid "Enable self-registration for users on the login pages"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:910
|
||||
#: common/models.py:925
|
||||
msgid "Enable SSO"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:911
|
||||
#: common/models.py:926
|
||||
msgid "Enable SSO on the login pages"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:916
|
||||
#: common/models.py:931
|
||||
msgid "Email required"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:917
|
||||
#: common/models.py:932
|
||||
msgid "Require user to supply mail on signup"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:922
|
||||
#: common/models.py:937
|
||||
msgid "Auto-fill SSO users"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:923
|
||||
#: common/models.py:938
|
||||
msgid "Automatically fill out user-details from SSO account-data"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:928
|
||||
#: common/models.py:943
|
||||
msgid "Mail twice"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:929
|
||||
#: common/models.py:944
|
||||
msgid "On signup ask users twice for their mail"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:934
|
||||
#: common/models.py:949
|
||||
msgid "Password twice"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:935
|
||||
#: common/models.py:950
|
||||
msgid "On signup ask users twice for their password"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:940
|
||||
#: common/models.py:955
|
||||
msgid "Group on signup"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:941
|
||||
#: common/models.py:956
|
||||
msgid "Group to which new users are assigned on registration"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:986
|
||||
#: common/models.py:1001
|
||||
msgid "Show subscribed parts"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:987
|
||||
#: common/models.py:1002
|
||||
msgid "Show subscribed parts on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:992
|
||||
#: common/models.py:1007
|
||||
msgid "Show subscribed categories"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:993
|
||||
#: common/models.py:1008
|
||||
msgid "Show subscribed part categories on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:998
|
||||
#: common/models.py:1013
|
||||
msgid "Show latest parts"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:999
|
||||
#: common/models.py:1014
|
||||
msgid "Show latest parts on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1004
|
||||
#: common/models.py:1019
|
||||
msgid "Recent Part Count"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1005
|
||||
#: common/models.py:1020
|
||||
msgid "Number of recent parts to display on index page"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1011
|
||||
#: common/models.py:1026
|
||||
msgid "Show unvalidated BOMs"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1012
|
||||
#: common/models.py:1027
|
||||
msgid "Show BOMs that await validation on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1017
|
||||
#: common/models.py:1032
|
||||
msgid "Show recent stock changes"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1018
|
||||
#: common/models.py:1033
|
||||
msgid "Show recently changed stock items on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1023
|
||||
#: common/models.py:1038
|
||||
msgid "Recent Stock Count"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1024
|
||||
#: common/models.py:1039
|
||||
msgid "Number of recent stock items to display on index page"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1029
|
||||
#: common/models.py:1044
|
||||
msgid "Show low stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1030
|
||||
#: common/models.py:1045
|
||||
msgid "Show low stock items on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1035
|
||||
#: common/models.py:1050
|
||||
msgid "Show depleted stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1036
|
||||
#: common/models.py:1051
|
||||
msgid "Show depleted stock items on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1041
|
||||
#: common/models.py:1056
|
||||
msgid "Show needed stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1042
|
||||
#: common/models.py:1057
|
||||
msgid "Show stock items needed for builds on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1047
|
||||
#: common/models.py:1062
|
||||
msgid "Show expired stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1048
|
||||
#: common/models.py:1063
|
||||
msgid "Show expired stock items on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1053
|
||||
#: common/models.py:1068
|
||||
msgid "Show stale stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1054
|
||||
#: common/models.py:1069
|
||||
msgid "Show stale stock items on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1059
|
||||
#: common/models.py:1074
|
||||
msgid "Show pending builds"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1060
|
||||
#: common/models.py:1075
|
||||
msgid "Show pending builds on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1065
|
||||
#: common/models.py:1080
|
||||
msgid "Show overdue builds"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1066
|
||||
#: common/models.py:1081
|
||||
msgid "Show overdue builds on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1071
|
||||
#: common/models.py:1086
|
||||
msgid "Show outstanding POs"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1072
|
||||
#: common/models.py:1087
|
||||
msgid "Show outstanding POs on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1077
|
||||
#: common/models.py:1092
|
||||
msgid "Show overdue POs"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1078
|
||||
#: common/models.py:1093
|
||||
msgid "Show overdue POs on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1083
|
||||
#: common/models.py:1098
|
||||
msgid "Show outstanding SOs"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1084
|
||||
#: common/models.py:1099
|
||||
msgid "Show outstanding SOs on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1089
|
||||
#: common/models.py:1104
|
||||
msgid "Show overdue SOs"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1090
|
||||
#: common/models.py:1105
|
||||
msgid "Show overdue SOs on the homepage"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1096
|
||||
#: common/models.py:1111
|
||||
msgid "Inline label display"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1097
|
||||
#: common/models.py:1112
|
||||
msgid "Display PDF labels in the browser, instead of downloading as a file"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1103
|
||||
#: common/models.py:1118
|
||||
msgid "Inline report display"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1104
|
||||
#: common/models.py:1119
|
||||
msgid "Display PDF reports in the browser, instead of downloading as a file"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1110
|
||||
#: common/models.py:1125
|
||||
msgid "Search Preview Results"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1111
|
||||
#: common/models.py:1126
|
||||
msgid "Number of results to show in search preview window"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1117
|
||||
#: common/models.py:1132
|
||||
msgid "Search Show Stock"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1118
|
||||
#: common/models.py:1133
|
||||
msgid "Display stock levels in search preview window"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1124
|
||||
#: common/models.py:1139
|
||||
msgid "Hide Inactive Parts"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1125
|
||||
#: common/models.py:1140
|
||||
msgid "Hide inactive parts in search preview window"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1131
|
||||
#: common/models.py:1146
|
||||
msgid "Show Quantity in Forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1132
|
||||
#: common/models.py:1147
|
||||
msgid "Display available part quantity in some forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1138
|
||||
#: common/models.py:1153
|
||||
msgid "Escape Key Closes Forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1139
|
||||
#: common/models.py:1154
|
||||
msgid "Use the escape key to close modal forms"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1145
|
||||
#: common/models.py:1160
|
||||
msgid "Fixed Navbar"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1146
|
||||
#: common/models.py:1161
|
||||
msgid "InvenTree navbar position is fixed to the top of the screen"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1211 company/forms.py:43
|
||||
#: common/models.py:1226 company/forms.py:43
|
||||
msgid "Price break quantity"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1218 company/serializers.py:264
|
||||
#: common/models.py:1233 company/serializers.py:264
|
||||
#: company/templates/company/supplier_part.html:256
|
||||
#: templates/js/translated/part.js:1508
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
|
||||
#: common/models.py:1219
|
||||
#: common/models.py:1234
|
||||
msgid "Unit price at specified quantity"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
+2889
-2839
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2875
-2838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2888
-2838
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+3028
-2855
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2853
-2836
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+3103
-2861
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2916
-2839
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2856
-2837
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+3102
-2790
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+2827
-2830
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+3152
-2771
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ class POList(generics.ListCreateAPIView):
|
||||
"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
|
||||
item = serializer.save()
|
||||
item.created_by = request.user
|
||||
item.save()
|
||||
@@ -404,7 +404,7 @@ class SOList(generics.ListCreateAPIView):
|
||||
"""
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
|
||||
item = serializer.save()
|
||||
item.created_by = request.user
|
||||
item.save()
|
||||
|
||||
@@ -772,7 +772,7 @@ class PurchaseOrderLineItem(OrderLineItem):
|
||||
def get_base_part(self):
|
||||
"""
|
||||
Return the base part.Part object for the line item
|
||||
|
||||
|
||||
Note: Returns None if the SupplierPart is not set!
|
||||
"""
|
||||
if self.part is None:
|
||||
|
||||
@@ -553,10 +553,10 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
|
||||
allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True)
|
||||
|
||||
quantity = InvenTreeDecimalField()
|
||||
|
||||
|
||||
allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
|
||||
fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True)
|
||||
|
||||
|
||||
sale_price = InvenTreeMoneySerializer(
|
||||
allow_null=True
|
||||
)
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
{% block sidebar %}
|
||||
{% url "po-detail" order.id as url %}
|
||||
{% include "sidebar_item.html" with url=url text="Return to Orders" icon="fa-undo" %}
|
||||
{% trans "Return to Orders" as text %}
|
||||
{% include "sidebar_item.html" with url=url text=text icon="fa-undo" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='order-items' text="Line Items" icon="fa-list-ol" %}
|
||||
{% include "sidebar_item.html" with label='received-items' text="Received Stock" icon="fa-sign-in-alt" %}
|
||||
{% include "sidebar_item.html" with label='order-attachments' text="Attachments" icon="fa-paperclip" %}
|
||||
{% include "sidebar_item.html" with label='order-notes' text="Notes" icon="fa-clipboard" %}
|
||||
{% trans "Line Items" as text %}
|
||||
{% include "sidebar_item.html" with label='order-items' text=text icon="fa-list-ol" %}
|
||||
{% trans "Received Stock" as text %}
|
||||
{% include "sidebar_item.html" with label='received-items' text=text icon="fa-sign-in-alt" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label='order-attachments' text=text icon="fa-paperclip" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label='order-notes' text=text icon="fa-clipboard" %}
|
||||
@@ -2,7 +2,11 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='order-items' text="Line Items" icon="fa-list-ol" %}
|
||||
{% include "sidebar_item.html" with label='order-builds' text="Build Orders" icon="fa-tools" %}
|
||||
{% include "sidebar_item.html" with label='order-attachments' text="Attachments" icon="fa-paperclip" %}
|
||||
{% include "sidebar_item.html" with label='order-notes' text="Notes" icon="fa-clipboard" %}
|
||||
{% trans "Line Items" as text %}
|
||||
{% include "sidebar_item.html" with label='order-items' text=text icon="fa-list-ol" %}
|
||||
{% trans "Build Orders" as text %}
|
||||
{% include "sidebar_item.html" with label='order-builds' text=text icon="fa-tools" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label='order-attachments' text=text icon="fa-paperclip" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label='order-notes' text=text icon="fa-clipboard" %}
|
||||
|
||||
@@ -228,7 +228,7 @@ class PurchaseOrderReceiveTest(OrderTest):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
||||
|
||||
self.assignRole('purchase_order.add')
|
||||
|
||||
self.url = reverse('api-po-receive', kwargs={'pk': 1})
|
||||
|
||||
@@ -406,7 +406,7 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
|
||||
def done(self, form_list, **kwargs):
|
||||
""" Once all the data is in, process it to add PurchaseOrderLineItem instances to the order """
|
||||
|
||||
|
||||
order = self.get_order()
|
||||
items = self.get_clean_items()
|
||||
|
||||
@@ -432,7 +432,7 @@ class PurchaseOrderUpload(FileManagementFormView):
|
||||
except IntegrityError:
|
||||
# PurchaseOrderLineItem already exists
|
||||
pass
|
||||
|
||||
|
||||
return HttpResponseRedirect(reverse('po-detail', kwargs={'pk': self.kwargs['pk']}))
|
||||
|
||||
|
||||
@@ -449,7 +449,7 @@ class SalesOrderExport(AjaxView):
|
||||
role_required = 'sales_order.view'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
|
||||
order = get_object_or_404(SalesOrder, pk=self.kwargs.get('pk', None))
|
||||
|
||||
export_format = request.GET.get('format', 'csv')
|
||||
|
||||
@@ -205,7 +205,7 @@ class BomItemResource(ModelResource):
|
||||
|
||||
# If we are not generating an "import" template,
|
||||
# just return the complete list of fields
|
||||
if not self.is_importing:
|
||||
if not getattr(self, 'is_importing', False):
|
||||
return fields
|
||||
|
||||
# Otherwise, remove some fields we are not interested in
|
||||
|
||||
@@ -169,7 +169,7 @@ class CategoryDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
API endpoint for detail view of a single PartCategory object
|
||||
"""
|
||||
|
||||
|
||||
serializer_class = part_serializers.CategorySerializer
|
||||
queryset = PartCategory.objects.all()
|
||||
|
||||
@@ -222,7 +222,7 @@ class CategoryParameterList(generics.ListAPIView):
|
||||
|
||||
if category is not None:
|
||||
try:
|
||||
|
||||
|
||||
category = PartCategory.objects.get(pk=category)
|
||||
|
||||
fetch_parent = str2bool(params.get('fetch_parent', True))
|
||||
@@ -734,7 +734,7 @@ class PartList(generics.ListCreateAPIView):
|
||||
raise ValidationError({
|
||||
'initial_stock_quantity': [_('Must be a valid quantity')],
|
||||
})
|
||||
|
||||
|
||||
initial_stock_location = request.data.get('initial_stock_location', None)
|
||||
|
||||
try:
|
||||
@@ -850,7 +850,7 @@ class PartList(generics.ListCreateAPIView):
|
||||
id_values.append(val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
queryset = queryset.exclude(pk__in=id_values)
|
||||
|
||||
# Exclude part variant tree?
|
||||
@@ -1096,7 +1096,7 @@ class BomFilter(rest_filters.FilterSet):
|
||||
queryset = queryset.filter(pk__in=pks)
|
||||
else:
|
||||
queryset = queryset.exclude(pk__in=pks)
|
||||
|
||||
|
||||
return queryset
|
||||
|
||||
# Filters for linked 'part'
|
||||
@@ -1257,7 +1257,7 @@ class BomList(generics.ListCreateAPIView):
|
||||
queryset = self.annotate_pricing(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
def include_pricing(self):
|
||||
"""
|
||||
Determine if pricing information should be included in the response
|
||||
@@ -1291,7 +1291,7 @@ class BomList(generics.ListCreateAPIView):
|
||||
|
||||
# Get default currency from settings
|
||||
default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY')
|
||||
|
||||
|
||||
if price:
|
||||
if currency and default_currency:
|
||||
try:
|
||||
@@ -1381,7 +1381,7 @@ class BomItemSubstituteList(generics.ListCreateAPIView):
|
||||
|
||||
serializer_class = part_serializers.BomItemSubstituteSerializer
|
||||
queryset = BomItemSubstitute.objects.all()
|
||||
|
||||
|
||||
filter_backends = [
|
||||
DjangoFilterBackend,
|
||||
filters.SearchFilter,
|
||||
|
||||
@@ -59,7 +59,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa
|
||||
|
||||
uids = []
|
||||
|
||||
def add_items(items, level, cascade):
|
||||
def add_items(items, level, cascade=True):
|
||||
# Add items at a given layer
|
||||
for item in items:
|
||||
|
||||
@@ -172,7 +172,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa
|
||||
|
||||
# Filter manufacturer parts
|
||||
manufacturer_parts = ManufacturerPart.objects.filter(part__pk=b_part.pk).prefetch_related('supplier_parts')
|
||||
|
||||
|
||||
for mp_idx, mp_part in enumerate(manufacturer_parts):
|
||||
|
||||
# Extract the "name" field of the Manufacturer (Company)
|
||||
@@ -190,7 +190,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa
|
||||
# Generate a column name for this manufacturer
|
||||
k_man = f'{_("Manufacturer")}_{mp_idx}'
|
||||
k_mpn = f'{_("MPN")}_{mp_idx}'
|
||||
|
||||
|
||||
try:
|
||||
manufacturer_cols[k_man].update({bom_idx: manufacturer_name})
|
||||
manufacturer_cols[k_mpn].update({bom_idx: manufacturer_mpn})
|
||||
@@ -200,7 +200,7 @@ def ExportBom(part, fmt='csv', cascade=False, max_levels=None, parameter_data=Fa
|
||||
|
||||
# We wish to include supplier data for this manufacturer part
|
||||
if supplier_data:
|
||||
|
||||
|
||||
for sp_idx, sp_part in enumerate(mp_part.supplier_parts.all()):
|
||||
|
||||
supplier_parts_used.add(sp_part)
|
||||
|
||||
@@ -1587,7 +1587,7 @@ class Part(MPTTModel):
|
||||
# Exclude any parts that this part is used *in* (to prevent recursive BOMs)
|
||||
used_in = self.get_used_in().all()
|
||||
|
||||
parts = parts.exclude(id__in=[item.part.id for item in used_in])
|
||||
parts = parts.exclude(id__in=[part.id for part in used_in])
|
||||
|
||||
return parts
|
||||
|
||||
@@ -2118,7 +2118,7 @@ class Part(MPTTModel):
|
||||
"""
|
||||
Returns True if the total stock for this part is less than the minimum stock level
|
||||
"""
|
||||
|
||||
|
||||
return self.get_stock_count() < self.minimum_stock
|
||||
|
||||
|
||||
@@ -2155,7 +2155,7 @@ class PartSellPriceBreak(common.models.PriceBreak):
|
||||
"""
|
||||
Represents a price break for selling this part
|
||||
"""
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_api_url():
|
||||
return reverse('api-part-sale-price-list')
|
||||
|
||||
@@ -446,9 +446,9 @@ class BomItemSerializer(InvenTreeModelSerializer):
|
||||
purchase_price_min = MoneyField(max_digits=10, decimal_places=6, read_only=True)
|
||||
|
||||
purchase_price_max = MoneyField(max_digits=10, decimal_places=6, read_only=True)
|
||||
|
||||
|
||||
purchase_price_avg = serializers.SerializerMethodField()
|
||||
|
||||
|
||||
purchase_price_range = serializers.SerializerMethodField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -520,7 +520,7 @@ class BomItemSerializer(InvenTreeModelSerializer):
|
||||
|
||||
def get_purchase_price_avg(self, obj):
|
||||
""" Return purchase price average """
|
||||
|
||||
|
||||
try:
|
||||
purchase_price_avg = obj.purchase_price_avg
|
||||
except AttributeError:
|
||||
|
||||
@@ -62,7 +62,7 @@ def notify_low_stock(part: part.models.Part):
|
||||
def notify_low_stock_if_required(part: part.models.Part):
|
||||
"""
|
||||
Check if the stock quantity has fallen below the minimum threshold of part.
|
||||
|
||||
|
||||
If true, notify the users who have subscribed to the part
|
||||
"""
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
{% block sidebar %}
|
||||
{% url "part-detail" part.id as url %}
|
||||
{% include "sidebar_link.html" with url=url text="Return to BOM" icon="fa-undo" %}
|
||||
{% trans "Return to BOM" as text %}
|
||||
{% include "sidebar_link.html" with url=url text=text icon="fa-undo" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block heading %}
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
|
||||
{% settings_value 'PART_SHOW_IMPORT' as show_import %}
|
||||
|
||||
{% include "sidebar_item.html" with label="subcategories" text="Subcategories" icon="fa-sitemap" %}
|
||||
{% include "sidebar_item.html" with label="parts" text="Parts" icon="fa-shapes" %}
|
||||
{% trans "Subcategories" as text %}
|
||||
{% include "sidebar_item.html" with label="subcategories" text=text icon="fa-sitemap" %}
|
||||
{% trans "Parts" as text %}
|
||||
{% include "sidebar_item.html" with label="parts" text=text icon="fa-shapes" %}
|
||||
{% if show_import and user.is_staff and roles.part.add %}
|
||||
{% url "part-import" as url %}
|
||||
{% include "sidebar_link.html" with url=url text="Import Parts" icon="fa-file-upload" %}
|
||||
{% trans "Import Parts" as text %}
|
||||
{% include "sidebar_link.html" with url=url text=text icon="fa-file-upload" %}
|
||||
{% endif %}
|
||||
{% if category %}
|
||||
{% include "sidebar_item.html" with label="parameters" text="Parameters" icon="fa-tasks" %}
|
||||
{% trans "Parameters" as text %}
|
||||
{% include "sidebar_item.html" with label="parameters" text=text icon="fa-tasks" %}
|
||||
{% endif %}
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
{% block sidebar %}
|
||||
{% url 'part-index' as url %}
|
||||
{% include "sidebar_link.html" with url=url text="Return to Parts" icon="fa-undo" %}
|
||||
{% trans "Return to Parts" as text %}
|
||||
{% include "sidebar_link.html" with url=url text=text icon="fa-undo" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -5,34 +5,49 @@
|
||||
{% settings_value "PART_INTERNAL_PRICE" as show_internal_price %}
|
||||
{% settings_value 'PART_SHOW_RELATED' as show_related %}
|
||||
|
||||
{% include "sidebar_item.html" with label="part-details" text="Details" icon="fa-shapes" %}
|
||||
{% include "sidebar_item.html" with label="part-parameters" text="Parameters" icon="fa-th-list" %}
|
||||
{% trans "Details" as text %}
|
||||
{% include "sidebar_item.html" with label="part-details" text=text icon="fa-shapes" %}
|
||||
{% trans "Parameters" as text %}
|
||||
{% include "sidebar_item.html" with label="part-parameters" text=text icon="fa-th-list" %}
|
||||
{% if part.is_template %}
|
||||
{% include "sidebar_item.html" with label="variants" text="Variants" icon="fa-shapes" %}
|
||||
{% trans "Variants" as text %}
|
||||
{% include "sidebar_item.html" with label="variants" text=text icon="fa-shapes" %}
|
||||
{% endif %}
|
||||
{% include "sidebar_item.html" with label="part-stock" text="Stock" icon="fa-boxes" %}
|
||||
{% trans "Stock" as text %}
|
||||
{% include "sidebar_item.html" with label="part-stock" text=text icon="fa-boxes" %}
|
||||
{% if part.assembly %}
|
||||
{% include "sidebar_item.html" with label="bom" text="Bill of Materials" icon="fa-list" %}
|
||||
{% trans "Bill of Materials" as text %}
|
||||
{% include "sidebar_item.html" with label="bom" text=text icon="fa-list" %}
|
||||
{% if roles.build.view %}
|
||||
{% include "sidebar_item.html" with label="build-orders" text="Build Orders" icon="fa-tools" %}
|
||||
{% trans "Build Orders" as text %}
|
||||
{% include "sidebar_item.html" with label="build-orders" text=text icon="fa-tools" %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if part.component %}
|
||||
{% include "sidebar_item.html" with label="used-in" text="Used In" icon="fa-layer-group" %}
|
||||
{% trans "Used In" as text %}
|
||||
{% include "sidebar_item.html" with label="used-in" text=text icon="fa-layer-group" %}
|
||||
{% endif %}
|
||||
{% include "sidebar_item.html" with label="pricing" text="Pricing" icon="fa-dollar-sign" %}
|
||||
{% trans "Pricing" as text %}
|
||||
{% include "sidebar_item.html" with label="pricing" text=text icon="fa-dollar-sign" %}
|
||||
{% if part.purchaseable and roles.purchase_order.view %}
|
||||
{% include "sidebar_item.html" with label="suppliers" text="Suppliers" icon="fa-building" %}
|
||||
{% include "sidebar_item.html" with label="purchase-orders" text="Purchase Orders" icon="fa-shopping-cart" %}
|
||||
{% trans "Suppliers" as text %}
|
||||
{% include "sidebar_item.html" with label="suppliers" text=text icon="fa-building" %}
|
||||
{% trans "Purchase Orders" as text %}
|
||||
{% include "sidebar_item.html" with label="purchase-orders" text=text icon="fa-shopping-cart" %}
|
||||
{% endif %}
|
||||
{% if part.salable and roles.sales_order.view %}
|
||||
{% include "sidebar_item.html" with label="sales-orders" text="Sales Orders" icon="fa-truck" %}
|
||||
{% trans "Sales Orders" as text %}
|
||||
{% include "sidebar_item.html" with label="sales-orders" text=text icon="fa-truck" %}
|
||||
{% endif %}
|
||||
{% if part.trackable %}
|
||||
{% include "sidebar_item.html" with label="test-templates" text="Test Templates" icon="fa-vial" %}
|
||||
{% trans "Test Templates" as text %}
|
||||
{% include "sidebar_item.html" with label="test-templates" text=text icon="fa-vial" %}
|
||||
{% endif %}
|
||||
{% if show_related %}
|
||||
{% include "sidebar_item.html" with label="related-parts" text="Related Parts" icon="fa-random" %}
|
||||
{% trans "Related Parts" as text %}
|
||||
{% include "sidebar_item.html" with label="related-parts" text=text icon="fa-random" %}
|
||||
{% endif %}
|
||||
{% include "sidebar_item.html" with label="part-attachments" text="Attachments" icon="fa-paperclip" %}
|
||||
{% include "sidebar_item.html" with label="part-notes" text="Notes" icon="fa-clipboard" %}
|
||||
{% trans "Attachments" as text %}
|
||||
{% include "sidebar_item.html" with label="part-attachments" text=text icon="fa-paperclip" %}
|
||||
{% trans "Notes" as text %}
|
||||
{% include "sidebar_item.html" with label="part-notes" text=text icon="fa-clipboard" %}
|
||||
|
||||
@@ -236,7 +236,7 @@ def settings_value(key, *args, **kwargs):
|
||||
|
||||
if 'user' in kwargs:
|
||||
return InvenTreeUserSetting.get_setting(key, user=kwargs['user'])
|
||||
|
||||
|
||||
return InvenTreeSetting.get_setting(key)
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ def keyvalue(dict, key):
|
||||
def call_method(obj, method_name, *args):
|
||||
"""
|
||||
enables calling model methods / functions from templates with arguments
|
||||
|
||||
|
||||
usage:
|
||||
{% call_method model_object 'fnc_name' argument1 %}
|
||||
"""
|
||||
|
||||
@@ -542,7 +542,7 @@ class PartAPITest(InvenTreeAPITestCase):
|
||||
# Check that there is a new manufacturer part *and* a new supplier part
|
||||
self.assertEqual(new_part.supplier_parts.count(), 1)
|
||||
self.assertEqual(new_part.manufacturer_parts.count(), 1)
|
||||
|
||||
|
||||
def test_strange_chars(self):
|
||||
"""
|
||||
Test that non-standard ASCII chars are accepted
|
||||
@@ -911,7 +911,7 @@ class BomItemTest(InvenTreeAPITestCase):
|
||||
|
||||
# How many BOM items currently exist in the database?
|
||||
n = BomItem.objects.count()
|
||||
|
||||
|
||||
url = reverse('api-bom-list')
|
||||
response = self.get(url, expected_code=200)
|
||||
self.assertEqual(len(response.data), n)
|
||||
@@ -962,7 +962,7 @@ class BomItemTest(InvenTreeAPITestCase):
|
||||
}
|
||||
|
||||
self.post(url, data, expected_code=201)
|
||||
|
||||
|
||||
# Now try to create a BomItem which references itself
|
||||
data['part'] = 100
|
||||
data['sub_part'] = 100
|
||||
@@ -1003,7 +1003,7 @@ class BomItemTest(InvenTreeAPITestCase):
|
||||
|
||||
# Now we will create some variant parts and stock
|
||||
for ii in range(5):
|
||||
|
||||
|
||||
# Create a variant part!
|
||||
variant = Part.objects.create(
|
||||
name=f"Variant_{ii}",
|
||||
|
||||
@@ -153,7 +153,7 @@ class BomItemTest(TestCase):
|
||||
subs = []
|
||||
|
||||
for ii in range(5):
|
||||
|
||||
|
||||
# Create a new part
|
||||
sub_part = Part.objects.create(
|
||||
name=f"Orphan {ii}",
|
||||
@@ -181,7 +181,7 @@ class BomItemTest(TestCase):
|
||||
|
||||
# There should be now 5 substitute parts available
|
||||
self.assertEqual(bom_item.substitutes.count(), 5)
|
||||
|
||||
|
||||
# Try to create a substitute which points to the same sub-part (should fail)
|
||||
with self.assertRaises(django_exceptions.ValidationError):
|
||||
BomItemSubstitute.objects.create(
|
||||
|
||||
@@ -370,7 +370,7 @@ class PartSubscriptionTests(TestCase):
|
||||
|
||||
# electronics / IC / MCU
|
||||
self.category = PartCategory.objects.get(pk=4)
|
||||
|
||||
|
||||
self.part = Part.objects.create(
|
||||
category=self.category,
|
||||
name='STM32F103',
|
||||
@@ -382,7 +382,7 @@ class PartSubscriptionTests(TestCase):
|
||||
"""
|
||||
Test basic subscription against a part
|
||||
"""
|
||||
|
||||
|
||||
# First check that the user is *not* subscribed to the part
|
||||
self.assertFalse(self.part.is_starred_by(self.user))
|
||||
|
||||
@@ -450,7 +450,7 @@ class PartSubscriptionTests(TestCase):
|
||||
"""
|
||||
Check that a parent category can be subscribed to
|
||||
"""
|
||||
|
||||
|
||||
# Top-level "electronics" category
|
||||
cat = PartCategory.objects.get(pk=1)
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ part_detail_urls = [
|
||||
url(r'^bom-export/?', views.BomExport.as_view(), name='bom-export'),
|
||||
url(r'^bom-download/?', views.BomDownload.as_view(), name='bom-download'),
|
||||
url(r'^validate-bom/', views.BomValidate.as_view(), name='bom-validate'),
|
||||
|
||||
|
||||
url(r'^pricing/', views.PartPricing.as_view(), name='part-pricing'),
|
||||
|
||||
url(r'^bom-upload/?', views.BomUpload.as_view(), name='upload-bom'),
|
||||
|
||||
@@ -459,7 +459,7 @@ class PartDetail(InvenTreeRoleMixin, DetailView):
|
||||
part = self.get_object()
|
||||
|
||||
ctx = part.get_context_data(self.request)
|
||||
|
||||
|
||||
context.update(**ctx)
|
||||
|
||||
# Pricing information
|
||||
@@ -1056,7 +1056,7 @@ class BomUpload(InvenTreeRoleMixin, FileManagementFormView):
|
||||
matches = sorted(matches, key=lambda item: item['match'], reverse=True)
|
||||
|
||||
part_options = [m['part'] for m in matches]
|
||||
|
||||
|
||||
# Supply list of part options for each row, sorted by how closely they match the part name
|
||||
row['item_options'] = part_options
|
||||
|
||||
@@ -1520,11 +1520,11 @@ class CategoryDetail(InvenTreeRoleMixin, DetailView):
|
||||
|
||||
# Prefetch parts parameters
|
||||
parts_parameters = category.prefetch_parts_parameters(cascade=cascade)
|
||||
|
||||
|
||||
# Get table headers (unique parameters names)
|
||||
context['headers'] = category.get_unique_parameters(cascade=cascade,
|
||||
prefetch=parts_parameters)
|
||||
|
||||
|
||||
# Insert part information
|
||||
context['headers'].insert(0, 'description')
|
||||
context['headers'].insert(0, 'part')
|
||||
|
||||
@@ -247,7 +247,7 @@ class ReportTemplateBase(ReportBase):
|
||||
"""
|
||||
|
||||
template_string = Template(self.filename_pattern)
|
||||
|
||||
|
||||
ctx = self.context(request)
|
||||
|
||||
context = Context(ctx)
|
||||
|
||||
@@ -106,7 +106,7 @@ class ReportTest(InvenTreeAPITestCase):
|
||||
# Filter by "enabled" status
|
||||
response = self.get(url, {'enabled': True})
|
||||
self.assertEqual(len(response.data), n)
|
||||
|
||||
|
||||
response = self.get(url, {'enabled': False})
|
||||
self.assertEqual(len(response.data), 0)
|
||||
|
||||
@@ -118,7 +118,7 @@ class ReportTest(InvenTreeAPITestCase):
|
||||
# Filter by "enabled" status
|
||||
response = self.get(url, {'enabled': True})
|
||||
self.assertEqual(len(response.data), 0)
|
||||
|
||||
|
||||
response = self.get(url, {'enabled': False})
|
||||
self.assertEqual(len(response.data), n)
|
||||
|
||||
@@ -199,7 +199,7 @@ class BuildReportTest(ReportTest):
|
||||
build = Build.objects.first()
|
||||
|
||||
response = self.get(url, {'build': build.pk})
|
||||
|
||||
|
||||
self.assertEqual(type(response), StreamingHttpResponse)
|
||||
|
||||
headers = response.headers
|
||||
|
||||
@@ -91,7 +91,7 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
Instead of "deleting" the StockItem
|
||||
(which may take a long time)
|
||||
we instead schedule it for deletion at a later date.
|
||||
|
||||
|
||||
The background worker will delete these in the future
|
||||
"""
|
||||
|
||||
@@ -134,7 +134,7 @@ class StockAdjustView(generics.CreateAPIView):
|
||||
queryset = StockItem.objects.none()
|
||||
|
||||
def get_serializer_context(self):
|
||||
|
||||
|
||||
context = super().get_serializer_context()
|
||||
|
||||
context['request'] = self.request
|
||||
@@ -348,7 +348,7 @@ class StockFilter(rest_filters.FilterSet):
|
||||
queryset = queryset.exclude(customer=None)
|
||||
else:
|
||||
queryset = queryset.filter(customer=None)
|
||||
|
||||
|
||||
return queryset
|
||||
|
||||
depleted = rest_filters.BooleanFilter(label='Depleted', method='filter_depleted')
|
||||
@@ -437,7 +437,7 @@ class StockList(generics.ListCreateAPIView):
|
||||
})
|
||||
|
||||
with transaction.atomic():
|
||||
|
||||
|
||||
# Create an initial stock item
|
||||
item = serializer.save()
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class ConvertStockItemForm(HelperForm):
|
||||
class CreateStockItemForm(HelperForm):
|
||||
"""
|
||||
Form for creating a new StockItem
|
||||
|
||||
|
||||
TODO: Migrate this form to the modern API forms interface
|
||||
"""
|
||||
|
||||
@@ -143,7 +143,7 @@ class CreateStockItemForm(HelperForm):
|
||||
class SerializeStockForm(HelperForm):
|
||||
"""
|
||||
Form for serializing a StockItem.
|
||||
|
||||
|
||||
TODO: Migrate this form to the modern API forms interface
|
||||
"""
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ class StockItem(MPTTModel):
|
||||
add_note = kwargs.pop('add_note', True)
|
||||
|
||||
notes = kwargs.pop('notes', '')
|
||||
|
||||
|
||||
if self.pk:
|
||||
# StockItem has already been saved
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class StockItemSerializerBrief(InvenTree.serializers.InvenTreeModelSerializer):
|
||||
|
||||
location_name = serializers.CharField(source='location', read_only=True)
|
||||
part_name = serializers.CharField(source='part.full_name', read_only=True)
|
||||
|
||||
|
||||
quantity = InvenTreeDecimalField()
|
||||
|
||||
class Meta:
|
||||
@@ -615,7 +615,7 @@ class StockCountSerializer(StockAdjustmentSerializer):
|
||||
|
||||
stock_item = item['pk']
|
||||
quantity = item['quantity']
|
||||
|
||||
|
||||
stock_item.stocktake(
|
||||
quantity,
|
||||
request.user,
|
||||
@@ -654,7 +654,7 @@ class StockRemoveSerializer(StockAdjustmentSerializer):
|
||||
"""
|
||||
|
||||
def save(self):
|
||||
|
||||
|
||||
request = self.context['request']
|
||||
|
||||
data = self.validated_data
|
||||
@@ -707,7 +707,7 @@ class StockTransferSerializer(StockAdjustmentSerializer):
|
||||
request = self.context['request']
|
||||
|
||||
data = self.validated_data
|
||||
|
||||
|
||||
items = data['items']
|
||||
notes = data.get('notes', '')
|
||||
location = data['location']
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
{% load static %}
|
||||
{% load inventree_extras %}
|
||||
|
||||
{% include "sidebar_item.html" with label='sublocations' text="Sublocations" icon="fa-sitemap" %}
|
||||
{% include "sidebar_item.html" with label='stock' text="Stock Items" icon="fa-boxes" %}
|
||||
{% trans "Sublocations" as text %}
|
||||
{% include "sidebar_item.html" with label='sublocations' text=text icon="fa-sitemap" %}
|
||||
{% trans "Stock Items" as text %}
|
||||
{% include "sidebar_item.html" with label='stock' text=text icon="fa-boxes" %}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user