mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-03 13:58:47 +00:00
Merge pull request #2966 from matmair/add-report-check
Add code128 template
This commit is contained in:
commit
362bc55479
@ -900,7 +900,7 @@ PLUGINS_ENABLED = _is_true(get_setting(
|
|||||||
PLUGIN_FILE = get_plugin_file()
|
PLUGIN_FILE = get_plugin_file()
|
||||||
|
|
||||||
# Plugin Directories (local plugins will be loaded from these directories)
|
# Plugin Directories (local plugins will be loaded from these directories)
|
||||||
PLUGIN_DIRS = ['plugin.builtin', 'barcodes.plugins', ]
|
PLUGIN_DIRS = ['plugin.builtin', ]
|
||||||
|
|
||||||
if not TESTING:
|
if not TESTING:
|
||||||
# load local deploy directory in prod
|
# load local deploy directory in prod
|
||||||
|
@ -18,7 +18,6 @@ from build.urls import build_urls
|
|||||||
from order.urls import order_urls
|
from order.urls import order_urls
|
||||||
from plugin.urls import get_plugin_urls
|
from plugin.urls import get_plugin_urls
|
||||||
|
|
||||||
from barcodes.api import barcode_api_urls
|
|
||||||
from common.api import common_api_urls, settings_api_urls
|
from common.api import common_api_urls, settings_api_urls
|
||||||
from part.api import part_api_urls, bom_api_urls
|
from part.api import part_api_urls, bom_api_urls
|
||||||
from company.api import company_api_urls
|
from company.api import company_api_urls
|
||||||
@ -28,6 +27,7 @@ from order.api import order_api_urls
|
|||||||
from label.api import label_api_urls
|
from label.api import label_api_urls
|
||||||
from report.api import report_api_urls
|
from report.api import report_api_urls
|
||||||
from plugin.api import plugin_api_urls
|
from plugin.api import plugin_api_urls
|
||||||
|
from plugin.barcode import barcode_api_urls
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
@ -59,7 +59,6 @@ if settings.PLUGINS_ENABLED:
|
|||||||
)
|
)
|
||||||
|
|
||||||
apipatterns += [
|
apipatterns += [
|
||||||
re_path(r'^barcode/', include(barcode_api_urls)),
|
|
||||||
re_path(r'^settings/', include(settings_api_urls)),
|
re_path(r'^settings/', include(settings_api_urls)),
|
||||||
re_path(r'^part/', include(part_api_urls)),
|
re_path(r'^part/', include(part_api_urls)),
|
||||||
re_path(r'^bom/', include(bom_api_urls)),
|
re_path(r'^bom/', include(bom_api_urls)),
|
||||||
@ -75,6 +74,7 @@ apipatterns += [
|
|||||||
|
|
||||||
# Plugin endpoints
|
# Plugin endpoints
|
||||||
re_path(r'^action/', ActionPluginView.as_view(), name='api-action-plugin'),
|
re_path(r'^action/', ActionPluginView.as_view(), name='api-action-plugin'),
|
||||||
|
re_path(r'^barcode/', include(barcode_api_urls)),
|
||||||
|
|
||||||
# Webhook enpoint
|
# Webhook enpoint
|
||||||
path('', include(common_api_urls)),
|
path('', include(common_api_urls)),
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
import plugin.builtin.barcode.mixins as mixin
|
|
||||||
import plugin.integration
|
|
||||||
|
|
||||||
|
|
||||||
hash_barcode = mixin.hash_barcode
|
|
||||||
|
|
||||||
|
|
||||||
class BarcodePlugin(mixin.BarcodeMixin, plugin.integration.IntegrationPluginBase):
|
|
||||||
"""
|
|
||||||
Legacy barcode plugin definition - will be replaced
|
|
||||||
Please use the new Integration Plugin API and the BarcodeMixin
|
|
||||||
"""
|
|
||||||
# TODO @matmair remove this with InvenTree 0.7.0
|
|
||||||
def __init__(self, barcode_data=None):
|
|
||||||
warnings.warn("using the BarcodePlugin is depreceated", DeprecationWarning)
|
|
||||||
super().__init__()
|
|
||||||
self.init(barcode_data)
|
|
@ -1,19 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
DigiKey barcode decoding
|
|
||||||
"""
|
|
||||||
|
|
||||||
from barcodes.barcode import BarcodePlugin
|
|
||||||
|
|
||||||
|
|
||||||
class DigikeyBarcodePlugin(BarcodePlugin):
|
|
||||||
|
|
||||||
PLUGIN_NAME = "DigikeyBarcode"
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
"""
|
|
||||||
TODO: Validation of Digikey barcodes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
return False
|
|
@ -265,6 +265,13 @@ class LabelConfig(AppConfig):
|
|||||||
'width': 70,
|
'width': 70,
|
||||||
'height': 24,
|
'height': 24,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'file': 'part_label_code128.html',
|
||||||
|
'name': 'Barcode Part Label',
|
||||||
|
'description': 'Simple part label with Code128 barcode',
|
||||||
|
'width': 70,
|
||||||
|
'height': 24,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
for label in labels:
|
for label in labels:
|
||||||
|
33
InvenTree/label/templates/label/part/part_label_code128.html
Normal file
33
InvenTree/label/templates/label/part/part_label_code128.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{% extends "label/label_base.html" %}
|
||||||
|
|
||||||
|
{% load barcode %}
|
||||||
|
|
||||||
|
{% block style %}
|
||||||
|
|
||||||
|
.qr {
|
||||||
|
position: fixed;
|
||||||
|
left: 0mm;
|
||||||
|
top: 0mm;
|
||||||
|
height: {{ height }}mm;
|
||||||
|
width: {{ height }}mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.part {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
display: inline;
|
||||||
|
position: absolute;
|
||||||
|
left: {{ height }}mm;
|
||||||
|
top: 2mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<img class='qr' src='{% barcode qr_data %}'>
|
||||||
|
|
||||||
|
<div class='part'>
|
||||||
|
{{ part.full_name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -5,20 +5,29 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
from django.urls import reverse
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from InvenTree.helpers import validateFilterString
|
from InvenTree.helpers import validateFilterString
|
||||||
|
from InvenTree.api_tester import InvenTreeAPITestCase
|
||||||
|
|
||||||
from .models import StockItemLabel, StockLocationLabel
|
from .models import StockItemLabel, StockLocationLabel, PartLabel
|
||||||
from stock.models import StockItem
|
from stock.models import StockItem
|
||||||
|
|
||||||
|
|
||||||
class LabelTest(TestCase):
|
class LabelTest(InvenTreeAPITestCase):
|
||||||
|
|
||||||
|
fixtures = [
|
||||||
|
'category',
|
||||||
|
'part',
|
||||||
|
'location',
|
||||||
|
'stock'
|
||||||
|
]
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
|
super().setUp()
|
||||||
# ensure the labels were created
|
# ensure the labels were created
|
||||||
apps.get_app_config('label').create_labels()
|
apps.get_app_config('label').create_labels()
|
||||||
|
|
||||||
@ -77,3 +86,13 @@ class LabelTest(TestCase):
|
|||||||
|
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
validateFilterString(bad_filter_string, model=StockItem)
|
validateFilterString(bad_filter_string, model=StockItem)
|
||||||
|
|
||||||
|
def test_label_rendering(self):
|
||||||
|
"""Test label rendering"""
|
||||||
|
|
||||||
|
labels = PartLabel.objects.all()
|
||||||
|
part = PartLabel.objects.first()
|
||||||
|
|
||||||
|
for label in labels:
|
||||||
|
url = reverse('api-part-label-print', kwargs={'pk': label.pk})
|
||||||
|
self.get(f'{url}?parts={part.pk}', expected_code=200)
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from django.urls import reverse, path, re_path
|
||||||
from django.urls import reverse
|
|
||||||
from django.urls import path, re_path
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
@ -12,8 +10,8 @@ from rest_framework.views import APIView
|
|||||||
from stock.models import StockItem
|
from stock.models import StockItem
|
||||||
from stock.serializers import StockItemSerializer
|
from stock.serializers import StockItemSerializer
|
||||||
|
|
||||||
from barcodes.plugins.inventree_barcode import InvenTreeBarcodePlugin
|
from plugin.builtin.barcodes.inventree_barcode import InvenTreeBarcodePlugin
|
||||||
from barcodes.barcode import hash_barcode
|
from plugin.builtin.barcodes.mixins import hash_barcode
|
||||||
from plugin import registry
|
from plugin import registry
|
||||||
|
|
||||||
|
|
@ -13,7 +13,8 @@ references model objects actually exist in the database.
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from barcodes.barcode import BarcodePlugin
|
from plugin import IntegrationPluginBase
|
||||||
|
from plugin.mixins import BarcodeMixin
|
||||||
|
|
||||||
from stock.models import StockItem, StockLocation
|
from stock.models import StockItem, StockLocation
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
@ -21,7 +22,7 @@ from part.models import Part
|
|||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeBarcodePlugin(BarcodePlugin):
|
class InvenTreeBarcodePlugin(BarcodeMixin, IntegrationPluginBase):
|
||||||
|
|
||||||
PLUGIN_NAME = "InvenTreeBarcode"
|
PLUGIN_NAME = "InvenTreeBarcode"
|
||||||
|
|
62
InvenTree/plugin/builtin/barcodes/test_inventree_barcode.py
Normal file
62
InvenTree/plugin/builtin/barcodes/test_inventree_barcode.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Unit tests for InvenTreeBarcodePlugin"""
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
from rest_framework import status
|
||||||
|
|
||||||
|
|
||||||
|
class TestInvenTreeBarcode(APITestCase):
|
||||||
|
|
||||||
|
fixtures = [
|
||||||
|
'category',
|
||||||
|
'part',
|
||||||
|
'location',
|
||||||
|
'stock'
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# Create a user for auth
|
||||||
|
user = get_user_model()
|
||||||
|
user.objects.create_user('testuser', 'test@testing.com', 'password')
|
||||||
|
|
||||||
|
self.client.login(username='testuser', password='password')
|
||||||
|
|
||||||
|
def test_errors(self):
|
||||||
|
"""
|
||||||
|
Test all possible error cases for assigment action
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_assert_error(barcode_data):
|
||||||
|
response = self.client.post(
|
||||||
|
reverse('api-barcode-link'), format='json',
|
||||||
|
data={
|
||||||
|
'barcode': barcode_data,
|
||||||
|
'stockitem': 521
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertIn('error', response.data)
|
||||||
|
|
||||||
|
# test with already existing stock
|
||||||
|
test_assert_error('{"stockitem": 521}')
|
||||||
|
|
||||||
|
# test with already existing stock location
|
||||||
|
test_assert_error('{"stocklocation": 7}')
|
||||||
|
|
||||||
|
# test with already existing part location
|
||||||
|
test_assert_error('{"part": 10004}')
|
||||||
|
|
||||||
|
# test with hash
|
||||||
|
test_assert_error('{"blbla": 10004}')
|
||||||
|
|
||||||
|
def test_scan(self):
|
||||||
|
"""
|
||||||
|
Test that a barcode can be scanned
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = self.client.post(reverse('api-barcode-scan'), format='json', data={'barcode': 'blbla=10004'})
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertIn('success', response.data)
|
@ -7,7 +7,7 @@ from ..builtin.integration.mixins import APICallMixin, AppMixin, LabelPrintingMi
|
|||||||
from common.notifications import SingleNotificationMethod, BulkNotificationMethod
|
from common.notifications import SingleNotificationMethod, BulkNotificationMethod
|
||||||
|
|
||||||
from ..builtin.action.mixins import ActionMixin
|
from ..builtin.action.mixins import ActionMixin
|
||||||
from ..builtin.barcode.mixins import BarcodeMixin
|
from ..builtin.barcodes.mixins import BarcodeMixin
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'APICallMixin',
|
'APICallMixin',
|
||||||
|
@ -264,57 +264,3 @@ class BarcodeAPITest(APITestCase):
|
|||||||
|
|
||||||
self.assertIn('error', data)
|
self.assertIn('error', data)
|
||||||
self.assertNotIn('success', data)
|
self.assertNotIn('success', data)
|
||||||
|
|
||||||
|
|
||||||
class TestInvenTreeBarcode(APITestCase):
|
|
||||||
|
|
||||||
fixtures = [
|
|
||||||
'category',
|
|
||||||
'part',
|
|
||||||
'location',
|
|
||||||
'stock'
|
|
||||||
]
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
# Create a user for auth
|
|
||||||
user = get_user_model()
|
|
||||||
user.objects.create_user('testuser', 'test@testing.com', 'password')
|
|
||||||
|
|
||||||
self.client.login(username='testuser', password='password')
|
|
||||||
|
|
||||||
def test_errors(self):
|
|
||||||
"""
|
|
||||||
Test all possible error cases for assigment action
|
|
||||||
"""
|
|
||||||
|
|
||||||
def test_assert_error(barcode_data):
|
|
||||||
response = self.client.post(
|
|
||||||
reverse('api-barcode-link'), format='json',
|
|
||||||
data={
|
|
||||||
'barcode': barcode_data,
|
|
||||||
'stockitem': 521
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
||||||
self.assertIn('error', response.data)
|
|
||||||
|
|
||||||
# test with already existing stock
|
|
||||||
test_assert_error('{"stockitem": 521}')
|
|
||||||
|
|
||||||
# test with already existing stock location
|
|
||||||
test_assert_error('{"stocklocation": 7}')
|
|
||||||
|
|
||||||
# test with already existing part location
|
|
||||||
test_assert_error('{"part": 10004}')
|
|
||||||
|
|
||||||
# test with hash
|
|
||||||
test_assert_error('{"blbla": 10004}')
|
|
||||||
|
|
||||||
def test_scan(self):
|
|
||||||
"""
|
|
||||||
Test that a barcode can be scanned
|
|
||||||
"""
|
|
||||||
|
|
||||||
response = self.client.post(reverse('api-barcode-scan'), format='json', data={'barcode': 'blbla=10004'})
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
||||||
self.assertIn('success', response.data)
|
|
Loading…
x
Reference in New Issue
Block a user