2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 13:05:42 +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

@ -0,0 +1,82 @@
"""API for location plugins"""
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from rest_framework import permissions
from rest_framework.exceptions import ParseError, NotFound
from rest_framework.response import Response
from rest_framework.views import APIView
from InvenTree.tasks import offload_task
from plugin import registry
from stock.models import StockItem, StockLocation
class LocatePluginView(APIView):
"""
Endpoint for using a custom plugin to identify or 'locate' a stock item or location
"""
permission_classes = [
permissions.IsAuthenticated,
]
def post(self, request, *args, **kwargs):
# Which plugin to we wish to use?
plugin = request.data.get('plugin', None)
if not plugin:
raise ParseError("'plugin' field must be supplied")
# Check that the plugin exists, and supports the 'locate' mixin
plugins = registry.with_mixin('locate')
if plugin not in [p.slug for p in plugins]:
raise ParseError(f"Plugin '{plugin}' is not installed, or does not support the location mixin")
# StockItem to identify
item_pk = request.data.get('item', None)
# StockLocation to identify
location_pk = request.data.get('location', None)
if not item_pk and not location_pk:
raise ParseError("Must supply either 'item' or 'location' parameter")
data = {
"success": "Identification plugin activated",
"plugin": plugin,
}
# StockItem takes priority
if item_pk:
try:
StockItem.objects.get(pk=item_pk)
offload_task('plugin.registry.call_function', plugin, 'locate_stock_item', item_pk)
data['item'] = item_pk
return Response(data)
except StockItem.DoesNotExist:
raise NotFound("StockItem matching PK '{item}' not found")
elif location_pk:
try:
StockLocation.objects.get(pk=location_pk)
offload_task('plugin.registry.call_function', plugin, 'locate_stock_location', location_pk)
data['location'] = location_pk
return Response(data)
except StockLocation.DoesNotExist:
raise NotFound("StockLocation matching PK {'location'} not found")
else:
raise NotFound()

View File

@ -0,0 +1,74 @@
"""Plugin mixin for locating stock items and locations"""
import logging
from plugin.helpers import MixinImplementationError
logger = logging.getLogger('inventree')
class LocateMixin:
"""
Mixin class which provides support for 'locating' inventory items,
for example identifying the location of a particular StockLocation.
Plugins could implement audible or visual cues to direct attention to the location,
with (for e.g.) LED strips or buzzers, or some other method.
The plugins may also be used to *deliver* a particular stock item to the user.
A class which implements this mixin may implement the following methods:
- locate_stock_item : Used to locate / identify a particular stock item
- locate_stock_location : Used to locate / identify a particular stock location
Refer to the default method implementations below for more information!
"""
class MixinMeta:
MIXIN_NAME = "Locate"
def __init__(self):
super().__init__()
self.add_mixin('locate', True, __class__)
def locate_stock_item(self, item_pk):
"""
Attempt to locate a particular StockItem
Arguments:
item_pk: The PK (primary key) of the StockItem to be located
The default implementation for locating a StockItem
attempts to locate the StockLocation where the item is located.
An attempt is only made if the StockItem is *in stock*
Note: A custom implemenation could always change this behaviour
"""
logger.info(f"LocateMixin: Attempting to locate StockItem pk={item_pk}")
from stock.models import StockItem
try:
item = StockItem.objects.get(pk=item_pk)
if item.in_stock and item.location is not None:
self.locate_stock_location(item.location.pk)
except StockItem.DoesNotExist:
logger.warning("LocateMixin: StockItem pk={item_pk} not found")
pass
def locate_stock_location(self, location_pk):
"""
Attempt to location a particular StockLocation
Arguments:
location_pk: The PK (primary key) of the StockLocation to be located
Note: The default implementation here does nothing!
"""
raise MixinImplementationError