Merge branch 'master' of https://github.com/inventree/InvenTree into plugin-2037

This commit is contained in:
Matthias 2021-12-02 17:16:26 +01:00
commit 329b00ae07
No known key found for this signature in database
GPG Key ID: F50EF5741D33E076
15 changed files with 136 additions and 47 deletions

View File

@ -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

View File

@ -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

2
.gitignore vendored
View File

@ -77,8 +77,6 @@ dev/
locale_stats.json
# node.js
package-lock.json
package.json
node_modules/
# maintenance locker

View File

@ -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):

View File

@ -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,

View 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),
),
]

View File

@ -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
"""

View 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),
),
]

View File

@ -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
"""

View File

@ -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')

View File

@ -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

View File

@ -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:

View File

@ -40,8 +40,8 @@
<link rel="stylesheet" href="{% static 'bootstrap-table/extensions/group-by-v2/bootstrap-table-group-by.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-table/extensions/filter-control/bootstrap-table-filter-control.css' %}">
<link rel='stylesheet' href='{% static "treegrid/css/jquery.treegrid.css" %}'>
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.css' %}">
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.css' %}">
<link rel="stylesheet" href="{% static 'fontawesome/css/brands.min.css' %}">
<link rel="stylesheet" href="{% static 'fontawesome/css/solid.min.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2.css' %}">
<link rel="stylesheet" href="{% static 'select2/css/select2-bootstrap-5-theme.css' %}">
<link rel="stylesheet" href="{% static 'fullcalendar/main.css' %}">

View File

@ -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'];

7
package.json Normal file
View File

@ -0,0 +1,7 @@
{
"dependencies": {
"eslint": "^8.3.0",
"eslint-config-google": "^0.14.0",
"markuplint": "^1.11.4"
}
}