mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Merge pull request #2402 from matmair/matmair/issue2400
Fix to big / small references
This commit is contained in:
		
							
								
								
									
										9
									
								
								.github/workflows/html.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/html.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
|   | ||||
							
								
								
									
										9
									
								
								.github/workflows/javascript.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/javascript.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -78,5 +78,4 @@ locale_stats.json | ||||
|  | ||||
| # node.js | ||||
| package-lock.json | ||||
| package.json | ||||
| node_modules/ | ||||
| @@ -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): | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
							
								
								
									
										18
									
								
								InvenTree/build/migrations/0034_alter_build_reference_int.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								InvenTree/build/migrations/0034_alter_build_reference_int.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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), | ||||
|         ), | ||||
|     ] | ||||
| @@ -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 | ||||
|     """ | ||||
|   | ||||
							
								
								
									
										23
									
								
								InvenTree/order/migrations/0054_auto_20211201_2139.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								InvenTree/order/migrations/0054_auto_20211201_2139.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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), | ||||
|         ), | ||||
|     ] | ||||
| @@ -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 | ||||
|     """ | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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: | ||||
|   | ||||
							
								
								
									
										7
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| { | ||||
|   "dependencies": { | ||||
|     "eslint": "^8.3.0", | ||||
|     "eslint-config-google": "^0.14.0", | ||||
|     "markuplint": "^1.11.4" | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user