mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-19 21:45:39 +00:00
Add Metadata to further models (#4410)
* Add metadata for ManufacturerPart * Add Metadata for SupplierPart * Add metadata to label models * Add metadata to order line items * Add metadata to shipment * Add metadata to Build and BuildItem * Add metadata to BomItem * Add metadata to PartParameterTemplate * Syntax, lint * Fix isort style * Lint * Correction of model name * Metadata for Reports * Fix silly error * Fix silly error * Correct model name * Correct model name * Correction * Correct company urls * Apply generic model to Report metadat * Rename/remove redundant import * Remove shadowing of report in loop variable * Update import ordering * More corrections * better docstrings * Correct names for API endpoints * Default to PO, required for api-doc to work * Changes by @matmair * Suppress metadata from Bom export * Add migration files * Increment API version * Add tests for all Metadata models, even previously existing ones * Update tests * Fix * Delay tests * Fix imports * Fix tests * API Version number * Remove unused import * isort * Revent unintended change of cache
This commit is contained in:
@ -13,11 +13,13 @@ from rest_framework.exceptions import NotFound
|
||||
|
||||
import common.models
|
||||
import InvenTree.helpers
|
||||
from InvenTree.mixins import ListAPI, RetrieveAPI, RetrieveUpdateDestroyAPI
|
||||
from InvenTree.mixins import (ListAPI, RetrieveAPI, RetrieveUpdateAPI,
|
||||
RetrieveUpdateDestroyAPI)
|
||||
from InvenTree.tasks import offload_task
|
||||
from part.models import Part
|
||||
from plugin.base.label import label as plugin_label
|
||||
from plugin.registry import registry
|
||||
from plugin.serializers import MetadataSerializer
|
||||
from stock.models import StockItem, StockLocation
|
||||
|
||||
from .models import PartLabel, StockItemLabel, StockLocationLabel
|
||||
@ -305,6 +307,16 @@ class StockItemLabelDetail(StockItemLabelMixin, RetrieveUpdateDestroyAPI):
|
||||
pass
|
||||
|
||||
|
||||
class StockItemLabelMetadata(RetrieveUpdateAPI):
|
||||
"""API endpoint for viewing / updating StockItemLabel metadata."""
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Return MetadataSerializer instance for a Company"""
|
||||
return MetadataSerializer(StockItemLabel, *args, **kwargs)
|
||||
|
||||
queryset = StockItemLabel.objects.all()
|
||||
|
||||
|
||||
class StockItemLabelPrint(StockItemLabelMixin, LabelPrintMixin, RetrieveAPI):
|
||||
"""API endpoint for printing a StockItemLabel object."""
|
||||
pass
|
||||
@ -337,6 +349,16 @@ class StockLocationLabelDetail(StockLocationLabelMixin, RetrieveUpdateDestroyAPI
|
||||
pass
|
||||
|
||||
|
||||
class StockLocationLabelMetadata(RetrieveUpdateAPI):
|
||||
"""API endpoint for viewing / updating StockLocationLabel metadata."""
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Return MetadataSerializer instance for a Company"""
|
||||
return MetadataSerializer(StockLocationLabel, *args, **kwargs)
|
||||
|
||||
queryset = StockLocationLabel.objects.all()
|
||||
|
||||
|
||||
class StockLocationLabelPrint(StockLocationLabelMixin, LabelPrintMixin, RetrieveAPI):
|
||||
"""API endpoint for printing a StockLocationLabel object."""
|
||||
pass
|
||||
@ -356,6 +378,16 @@ class PartLabelList(PartLabelMixin, LabelListView):
|
||||
pass
|
||||
|
||||
|
||||
class PartLabelMetadata(RetrieveUpdateAPI):
|
||||
"""API endpoint for viewing / updating PartLabel metadata."""
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
"""Return MetadataSerializer instance for a Company"""
|
||||
return MetadataSerializer(PartLabel, *args, **kwargs)
|
||||
|
||||
queryset = PartLabel.objects.all()
|
||||
|
||||
|
||||
class PartLabelDetail(PartLabelMixin, RetrieveUpdateDestroyAPI):
|
||||
"""API endpoint for a single PartLabel object."""
|
||||
pass
|
||||
@ -373,6 +405,7 @@ label_api_urls = [
|
||||
# Detail views
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'print/?', StockItemLabelPrint.as_view(), name='api-stockitem-label-print'),
|
||||
re_path(r'metadata/', StockItemLabelMetadata.as_view(), name='api-stockitem-label-metadata'),
|
||||
re_path(r'^.*$', StockItemLabelDetail.as_view(), name='api-stockitem-label-detail'),
|
||||
])),
|
||||
|
||||
@ -385,6 +418,7 @@ label_api_urls = [
|
||||
# Detail views
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'print/?', StockLocationLabelPrint.as_view(), name='api-stocklocation-label-print'),
|
||||
re_path(r'metadata/', StockLocationLabelMetadata.as_view(), name='api-stocklocation-label-metadata'),
|
||||
re_path(r'^.*$', StockLocationLabelDetail.as_view(), name='api-stocklocation-label-detail'),
|
||||
])),
|
||||
|
||||
@ -397,6 +431,7 @@ label_api_urls = [
|
||||
# Detail views
|
||||
re_path(r'^(?P<pk>\d+)/', include([
|
||||
re_path(r'^print/', PartLabelPrint.as_view(), name='api-part-label-print'),
|
||||
re_path(r'^metadata/', PartLabelMetadata.as_view(), name='api-part-label-metadata'),
|
||||
re_path(r'^.*$', PartLabelDetail.as_view(), name='api-part-label-detail'),
|
||||
])),
|
||||
|
||||
|
28
InvenTree/label/migrations/0009_auto_20230317_0816.py
Normal file
28
InvenTree/label/migrations/0009_auto_20230317_0816.py
Normal file
@ -0,0 +1,28 @@
|
||||
# Generated by Django 3.2.18 on 2023-03-17 08:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('label', '0008_auto_20210708_2106'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='partlabel',
|
||||
name='metadata',
|
||||
field=models.JSONField(blank=True, help_text='JSON metadata field, for use by external plugins', null=True, verbose_name='Plugin Metadata'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='stockitemlabel',
|
||||
name='metadata',
|
||||
field=models.JSONField(blank=True, help_text='JSON metadata field, for use by external plugins', null=True, verbose_name='Plugin Metadata'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='stocklocationlabel',
|
||||
name='metadata',
|
||||
field=models.JSONField(blank=True, help_text='JSON metadata field, for use by external plugins', null=True, verbose_name='Plugin Metadata'),
|
||||
),
|
||||
]
|
@ -17,6 +17,7 @@ import common.models
|
||||
import part.models
|
||||
import stock.models
|
||||
from InvenTree.helpers import normalize, validateFilterString
|
||||
from plugin.models import MetadataMixin
|
||||
|
||||
try:
|
||||
from django_weasyprint import WeasyTemplateResponseMixin
|
||||
@ -70,7 +71,7 @@ class WeasyprintLabelMixin(WeasyTemplateResponseMixin):
|
||||
self.pdf_filename = kwargs.get('filename', 'label.pdf')
|
||||
|
||||
|
||||
class LabelTemplate(models.Model):
|
||||
class LabelTemplate(MetadataMixin, models.Model):
|
||||
"""Base class for generic, filterable labels."""
|
||||
|
||||
class Meta:
|
||||
|
@ -130,3 +130,21 @@ class LabelTest(InvenTreeAPITestCase):
|
||||
self.assertIn("http://testserver/part/1/", content)
|
||||
self.assertIn("image: /static/img/blank_image.png", content)
|
||||
self.assertIn("logo: /static/img/inventree.png", content)
|
||||
|
||||
def test_metadata(self):
|
||||
"""Unit tests for the metadata field."""
|
||||
for model in [StockItemLabel, StockLocationLabel, PartLabel]:
|
||||
p = model.objects.first()
|
||||
self.assertIsNone(p.metadata)
|
||||
|
||||
self.assertIsNone(p.get_metadata('test'))
|
||||
self.assertEqual(p.get_metadata('test', backup_value=123), 123)
|
||||
|
||||
# Test update via the set_metadata() method
|
||||
p.set_metadata('test', 3)
|
||||
self.assertEqual(p.get_metadata('test'), 3)
|
||||
|
||||
for k in ['apple', 'banana', 'carrot', 'carrot', 'banana']:
|
||||
p.set_metadata(k, k)
|
||||
|
||||
self.assertEqual(len(p.metadata.keys()), 4)
|
||||
|
Reference in New Issue
Block a user