2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-01 03:00:54 +00:00

Merge pull request #2957 from SchrodingersGat/locate-mixin

Adds plugin mixin to "locate" items
This commit is contained in:
Oliver
2022-05-16 22:57:20 +10:00
committed by GitHub
28 changed files with 789 additions and 32 deletions

View File

@ -43,6 +43,8 @@ from order.serializers import PurchaseOrderSerializer
from part.models import BomItem, Part, PartCategory
from part.serializers import PartBriefSerializer
from plugin.serializers import MetadataSerializer
from stock.admin import StockItemResource
from stock.models import StockLocation, StockItem
from stock.models import StockItemTracking
@ -92,6 +94,15 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
return self.serializer_class(*args, **kwargs)
class StockMetadata(generics.RetrieveUpdateAPIView):
"""API endpoint for viewing / updating StockItem metadata"""
def get_serializer(self, *args, **kwargs):
return MetadataSerializer(StockItem, *args, **kwargs)
queryset = StockItem.objects.all()
class StockItemContextMixin:
""" Mixin class for adding StockItem object to serializer context """
@ -1368,6 +1379,15 @@ class StockTrackingList(generics.ListAPIView):
]
class LocationMetadata(generics.RetrieveUpdateAPIView):
"""API endpoint for viewing / updating StockLocation metadata"""
def get_serializer(self, *args, **kwargs):
return MetadataSerializer(StockLocation, *args, **kwargs)
queryset = StockLocation.objects.all()
class LocationDetail(generics.RetrieveUpdateDestroyAPIView):
""" API endpoint for detail view of StockLocation object
@ -1385,7 +1405,14 @@ stock_api_urls = [
re_path(r'^tree/', StockLocationTree.as_view(), name='api-location-tree'),
re_path(r'^(?P<pk>\d+)/', LocationDetail.as_view(), name='api-location-detail'),
# Stock location detail endpoints
re_path(r'^(?P<pk>\d+)/', include([
re_path(r'^metadata/', LocationMetadata.as_view(), name='api-location-metadata'),
re_path(r'^.*$', LocationDetail.as_view(), name='api-location-detail'),
])),
re_path(r'^.*$', StockLocationList.as_view(), name='api-location-list'),
])),
@ -1417,8 +1444,9 @@ stock_api_urls = [
# Detail views for a single stock item
re_path(r'^(?P<pk>\d+)/', include([
re_path(r'^serialize/', StockItemSerialize.as_view(), name='api-stock-item-serialize'),
re_path(r'^install/', StockItemInstall.as_view(), name='api-stock-item-install'),
re_path(r'^metadata/', StockMetadata.as_view(), name='api-stock-item-metadata'),
re_path(r'^serialize/', StockItemSerialize.as_view(), name='api-stock-item-serialize'),
re_path(r'^uninstall/', StockItemUninstall.as_view(), name='api-stock-item-uninstall'),
re_path(r'^.*$', StockDetail.as_view(), name='api-stock-detail'),
])),

View File

@ -0,0 +1,27 @@
# Generated by Django 3.2.13 on 2022-05-15 14:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('stock', '0074_alter_stockitem_batch'),
]
operations = [
migrations.AddField(
model_name='stockitem',
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='stocklocation',
name='metadata',
field=models.JSONField(blank=True, help_text='JSON metadata field, for use by external plugins', null=True, verbose_name='Plugin Metadata'),
),
migrations.AlterUniqueTogether(
name='stocklocation',
unique_together=set(),
),
]

View File

@ -38,6 +38,7 @@ import common.models
import report.models
import label.models
from plugin.models import MetadataMixin
from plugin.events import trigger_event
from InvenTree.status_codes import StockStatus, StockHistoryCode
@ -51,7 +52,7 @@ from company import models as CompanyModels
from part import models as PartModels
class StockLocation(InvenTreeTree):
class StockLocation(MetadataMixin, InvenTreeTree):
""" Organization tree for StockItem objects
A "StockLocation" can be considered a warehouse, or storage location
Stock locations can be heirarchical as required
@ -242,7 +243,7 @@ def generate_batch_code():
return Template(batch_template).render(context)
class StockItem(MPTTModel):
class StockItem(MetadataMixin, MPTTModel):
"""
A StockItem object represents a quantity of physical instances of a part.

View File

@ -1,5 +1,6 @@
{% extends "page_base.html" %}
{% load static %}
{% load plugin_extras %}
{% load inventree_extras %}
{% load status_codes %}
{% load i18n %}
@ -18,7 +19,6 @@
<div id="breadcrumb-tree"></div>
{% endblock breadcrumb_tree %}
{% block heading %}
{% trans "Stock Item" %}: {{ item.part.full_name}}
{% endblock heading %}
@ -29,6 +29,12 @@
{% url 'admin:stock_stockitem_change' item.pk as url %}
{% include "admin_button.html" with url=url %}
{% endif %}
{% mixin_available "locate" as locate_available %}
{% if plugins_enabled and locate_available %}
<button id='locate-item-button' title='{% trans "Locate stock item" %}' class='btn btn-outline-secondary' typy='button'>
<span class='fas fa-search-location'></span>
</button>
{% endif %}
{% if barcodes %}
<!-- Barcode actions menu -->
<div class='btn-group' role='group'>
@ -514,6 +520,14 @@ $("#barcode-scan-into-location").click(function() {
});
});
{% if plugins_enabled %}
$('#locate-item-button').click(function() {
locateItemOrLocation({
item: {{ item.pk }},
});
});
{% endif %}
function itemAdjust(action) {
inventreeGet(

View File

@ -1,6 +1,7 @@
{% extends "stock/stock_app_base.html" %}
{% load static %}
{% load inventree_extras %}
{% load plugin_extras %}
{% load i18n %}
{% block sidebar %}
@ -27,6 +28,14 @@
{% include "admin_button.html" with url=url %}
{% endif %}
{% mixin_available "locate" as locate_available %}
{% if location and plugins_enabled and locate_available %}
<button id='locate-location-button' title='{% trans "Locate stock location" %}' class='btn btn-outline-secondary' typy='button'>
<span class='fas fa-search-location'></span>
</button>
{% endif %}
{% if barcodes %}
<!-- Barcode actions menu -->
{% if location %}
@ -206,6 +215,14 @@
{% block js_ready %}
{{ block.super }}
{% if plugins_enabled and location %}
$('#locate-location-button').click(function() {
locateItemOrLocation({
location: {{ location.pk }},
});
});
{% endif %}
onPanelLoad('sublocations', function() {
loadStockLocationTable($('#sublocation-table'), {
params: {