mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-19 13:35:40 +00:00
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
"""
|
||||
|
||||
|
@ -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')
|
||||
|
Reference in New Issue
Block a user