diff --git a/.github/workflows/html.yaml b/.github/workflows/html.yaml
index d0084ae032..580962771e 100644
--- a/.github/workflows/html.yaml
+++ b/.github/workflows/html.yaml
@@ -23,11 +23,13 @@ jobs:
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- - name: Install node.js
- uses: actions/setup-node@v2
- - run: npm install
- name: Checkout Code
uses: actions/checkout@v2
+ - name: Install node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+ - run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
@@ -41,7 +43,6 @@ jobs:
invoke static
- name: Check HTML Files
run: |
- npm install markuplint
npx markuplint InvenTree/build/templates/build/*.html
npx markuplint InvenTree/company/templates/company/*.html
npx markuplint InvenTree/order/templates/order/*.html
diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml
index a07b516ac6..98251b2426 100644
--- a/.github/workflows/javascript.yaml
+++ b/.github/workflows/javascript.yaml
@@ -23,11 +23,13 @@ jobs:
INVENTREE_MEDIA_ROOT: ./media
INVENTREE_STATIC_ROOT: ./static
steps:
- - name: Install node.js
- uses: actions/setup-node@v2
- - run: npm install
- name: Checkout Code
uses: actions/checkout@v2
+ - name: Install node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+ - run: npm install
- name: Setup Python
uses: actions/setup-python@v2
with:
@@ -45,6 +47,5 @@ jobs:
python check_js_templates.py
- name: Lint Javascript Files
run: |
- npm install eslint eslint-config-google
invoke render-js-files
npx eslint js_tmp/*.js
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 8db4f189ac..4bc0bb1389 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,8 +77,6 @@ dev/
locale_stats.json
# node.js
-package-lock.json
-package.json
node_modules/
# maintenance locker
diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py
index 0448a69781..b42d54cbe9 100644
--- a/InvenTree/InvenTree/models.py
+++ b/InvenTree/InvenTree/models.py
@@ -49,6 +49,9 @@ class ReferenceIndexingMixin(models.Model):
"""
A mixin for keeping track of numerical copies of the "reference" field.
+ !!DANGER!! always add `ReferenceIndexingSerializerMixin`to all your models serializers to
+ ensure the reference field is not too big
+
Here, we attempt to convert a "reference" field value (char) to an integer,
for performing fast natural sorting.
@@ -69,22 +72,25 @@ class ReferenceIndexingMixin(models.Model):
reference = getattr(self, 'reference', '')
- # Default value if we cannot convert to an integer
- ref_int = 0
+ self.reference_int = extract_int(reference)
- # Look at the start of the string - can it be "integerized"?
- result = re.match(r"^(\d+)", reference)
+ reference_int = models.BigIntegerField(default=0)
- if result and len(result.groups()) == 1:
- ref = result.groups()[0]
- try:
- ref_int = int(ref)
- except:
- ref_int = 0
- self.reference_int = ref_int
+def extract_int(reference):
+ # Default value if we cannot convert to an integer
+ ref_int = 0
- reference_int = models.IntegerField(default=0)
+ # Look at the start of the string - can it be "integerized"?
+ result = re.match(r"^(\d+)", reference)
+
+ if result and len(result.groups()) == 1:
+ ref = result.groups()[0]
+ try:
+ ref_int = int(ref)
+ except:
+ ref_int = 0
+ return ref_int
class InvenTreeAttachment(models.Model):
diff --git a/InvenTree/InvenTree/serializers.py b/InvenTree/InvenTree/serializers.py
index 3785cfb292..59ba0295cb 100644
--- a/InvenTree/InvenTree/serializers.py
+++ b/InvenTree/InvenTree/serializers.py
@@ -16,6 +16,7 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError as DjangoValidationError
from django.utils.translation import ugettext_lazy as _
+from django.db import models
from djmoney.contrib.django_rest_framework.fields import MoneyField
from djmoney.money import Money
@@ -27,6 +28,8 @@ from rest_framework.fields import empty
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import DecimalField
+from .models import extract_int
+
class InvenTreeMoneySerializer(MoneyField):
"""
@@ -239,6 +242,17 @@ class InvenTreeModelSerializer(serializers.ModelSerializer):
return data
+class ReferenceIndexingSerializerMixin():
+ """
+ This serializer mixin ensures the the reference is not to big / small
+ for the BigIntegerField
+ """
+ def validate_reference(self, value):
+ if extract_int(value) > models.BigIntegerField.MAX_BIGINT:
+ raise serializers.ValidationError('reference is to to big')
+ return value
+
+
class InvenTreeAttachmentSerializerField(serializers.FileField):
"""
Override the DRF native FileField serializer,
diff --git a/InvenTree/build/migrations/0034_alter_build_reference_int.py b/InvenTree/build/migrations/0034_alter_build_reference_int.py
new file mode 100644
index 0000000000..8b14d3812e
--- /dev/null
+++ b/InvenTree/build/migrations/0034_alter_build_reference_int.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.5 on 2021-12-01 21:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('build', '0033_auto_20211128_0151'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='build',
+ name='reference_int',
+ field=models.BigIntegerField(default=0),
+ ),
+ ]
diff --git a/InvenTree/build/serializers.py b/InvenTree/build/serializers.py
index 35a3bb3baa..2431855d3c 100644
--- a/InvenTree/build/serializers.py
+++ b/InvenTree/build/serializers.py
@@ -16,7 +16,7 @@ from rest_framework import serializers
from rest_framework.serializers import ValidationError
from InvenTree.serializers import InvenTreeModelSerializer, InvenTreeAttachmentSerializer
-from InvenTree.serializers import UserSerializerBrief
+from InvenTree.serializers import UserSerializerBrief, ReferenceIndexingSerializerMixin
import InvenTree.helpers
from InvenTree.serializers import InvenTreeDecimalField
@@ -32,7 +32,7 @@ from users.serializers import OwnerSerializer
from .models import Build, BuildItem, BuildOrderAttachment
-class BuildSerializer(InvenTreeModelSerializer):
+class BuildSerializer(ReferenceIndexingSerializerMixin, InvenTreeModelSerializer):
"""
Serializes a Build object
"""
diff --git a/InvenTree/order/migrations/0054_auto_20211201_2139.py b/InvenTree/order/migrations/0054_auto_20211201_2139.py
new file mode 100644
index 0000000000..8a66bbea12
--- /dev/null
+++ b/InvenTree/order/migrations/0054_auto_20211201_2139.py
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.5 on 2021-12-01 21:39
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('order', '0053_auto_20211128_0151'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='purchaseorder',
+ name='reference_int',
+ field=models.BigIntegerField(default=0),
+ ),
+ migrations.AlterField(
+ model_name='salesorder',
+ name='reference_int',
+ field=models.BigIntegerField(default=0),
+ ),
+ ]
diff --git a/InvenTree/order/serializers.py b/InvenTree/order/serializers.py
index 0528d57596..38a058ae6d 100644
--- a/InvenTree/order/serializers.py
+++ b/InvenTree/order/serializers.py
@@ -24,6 +24,7 @@ from InvenTree.serializers import InvenTreeAttachmentSerializer
from InvenTree.serializers import InvenTreeModelSerializer
from InvenTree.serializers import InvenTreeDecimalField
from InvenTree.serializers import InvenTreeMoneySerializer
+from InvenTree.serializers import ReferenceIndexingSerializerMixin
from InvenTree.status_codes import StockStatus
from part.serializers import PartBriefSerializer
@@ -39,7 +40,7 @@ from .models import SalesOrderAllocation
from users.serializers import OwnerSerializer
-class POSerializer(InvenTreeModelSerializer):
+class POSerializer(ReferenceIndexingSerializerMixin, InvenTreeModelSerializer):
""" Serializer for a PurchaseOrder object """
def __init__(self, *args, **kwargs):
@@ -394,7 +395,7 @@ class POAttachmentSerializer(InvenTreeAttachmentSerializer):
]
-class SalesOrderSerializer(InvenTreeModelSerializer):
+class SalesOrderSerializer(ReferenceIndexingSerializerMixin, InvenTreeModelSerializer):
"""
Serializers for the SalesOrder object
"""
diff --git a/InvenTree/order/test_api.py b/InvenTree/order/test_api.py
index 94e9696e0a..44effe9fb6 100644
--- a/InvenTree/order/test_api.py
+++ b/InvenTree/order/test_api.py
@@ -105,6 +105,25 @@ class PurchaseOrderTest(OrderTest):
self.assertEqual(data['pk'], 1)
self.assertEqual(data['description'], 'Ordering some screws')
+ def test_po_reference(self):
+ """test that a reference with a too big / small reference is not possible"""
+ # get permissions
+ self.assignRole('purchase_order.add')
+
+ url = reverse('api-po-list')
+ huge_numer = 9223372036854775808
+
+ # too big
+ self.post(
+ url,
+ {
+ 'supplier': 1,
+ 'reference': huge_numer,
+ 'description': 'PO not created via the API',
+ },
+ expected_code=400
+ )
+
def test_po_attachments(self):
url = reverse('api-po-attachment-list')
diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py
index 8457ca39ab..0aa63687c9 100644
--- a/InvenTree/stock/models.py
+++ b/InvenTree/stock/models.py
@@ -7,7 +7,6 @@ Stock database model definitions
from __future__ import unicode_literals
import os
-import re
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError, FieldError
@@ -39,6 +38,7 @@ import label.models
from InvenTree.status_codes import StockStatus, StockHistoryCode
from InvenTree.models import InvenTreeTree, InvenTreeAttachment
from InvenTree.fields import InvenTreeModelMoneyField, InvenTreeURLField
+from InvenTree.serializers import extract_int
from users.models import Owner
@@ -236,17 +236,7 @@ class StockItem(MPTTModel):
serial_int = 0
if serial is not None:
-
- serial = str(serial)
-
- # Look at the start of the string - can it be "integerized"?
- result = re.match(r'^(\d+)', serial)
-
- if result and len(result.groups()) == 1:
- try:
- serial_int = int(result.groups()[0])
- except:
- serial_int = 0
+ serial_int = extract_int(str(serial))
self.serial_int = serial_int
diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py
index c74d674275..9bd5ea64be 100644
--- a/InvenTree/stock/serializers.py
+++ b/InvenTree/stock/serializers.py
@@ -32,7 +32,7 @@ from company.serializers import SupplierPartSerializer
import InvenTree.helpers
import InvenTree.serializers
-from InvenTree.serializers import InvenTreeDecimalField
+from InvenTree.serializers import InvenTreeDecimalField, extract_int
from part.serializers import PartBriefSerializer
@@ -73,6 +73,11 @@ class StockItemSerializerBrief(InvenTree.serializers.InvenTreeModelSerializer):
'uid',
]
+ def validate_serial(self, value):
+ if extract_int(value) > 2147483647:
+ raise serializers.ValidationError('serial is to to big')
+ return value
+
class StockItemSerializer(InvenTree.serializers.InvenTreeModelSerializer):
""" Serializer for a StockItem:
diff --git a/InvenTree/templates/base.html b/InvenTree/templates/base.html
index de0d14c716..5636af86e8 100644
--- a/InvenTree/templates/base.html
+++ b/InvenTree/templates/base.html
@@ -40,8 +40,8 @@
-
-
+
+
diff --git a/InvenTree/templates/js/translated/part.js b/InvenTree/templates/js/translated/part.js
index 1bf025b629..0a27f2ba2f 100644
--- a/InvenTree/templates/js/translated/part.js
+++ b/InvenTree/templates/js/translated/part.js
@@ -153,12 +153,7 @@ function partFields(options={}) {
delete fields['default_expiry'];
}
- // Additional fields when "creating" a new part
- if (options.create) {
-
- // No supplier parts available yet
- delete fields['default_supplier'];
-
+ if (options.create || options.duplicate) {
if (global_settings.PART_CREATE_INITIAL) {
fields.initial_stock = {
@@ -187,6 +182,13 @@ function partFields(options={}) {
group: 'create',
};
}
+ }
+
+ // Additional fields when "creating" a new part
+ if (options.create) {
+
+ // No supplier parts available yet
+ delete fields['default_supplier'];
fields.copy_category_parameters = {
type: 'boolean',
@@ -349,6 +351,10 @@ function duplicatePart(pk, options={}) {
duplicate: pk,
});
+ if (fields.initial_stock_location) {
+ fields.initial_stock_location.value = data.default_location;
+ }
+
// Remove "default_supplier" field
delete fields['default_supplier'];
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000..b4f14ec92f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,7 @@
+{
+ "dependencies": {
+ "eslint": "^8.3.0",
+ "eslint-config-google": "^0.14.0",
+ "markuplint": "^1.11.4"
+ }
+}