mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'inventree:master' into matmair/issue2201
This commit is contained in:
commit
e3dfb1295b
@ -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.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/el/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/el/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
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.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/he/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/he/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/id/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/id/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/ko/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/ko/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/nl/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/nl/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/no/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/no/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/sv/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/sv/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/th/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/th/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
InvenTree/locale/vi/LC_MESSAGES/django.mo
Normal file
BIN
InvenTree/locale/vi/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
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
Loading…
Reference in New Issue
Block a user