Updated templates and a lot of manual testing

This commit is contained in:
eeintech 2021-01-12 13:16:04 -05:00
parent 9eace09e0e
commit b6135fda74
7 changed files with 162 additions and 30 deletions

View File

@ -145,3 +145,22 @@ def get_color_theme_css(username):
inventree_css_static_url = os.path.join(settings.STATIC_URL, inventree_css_sheet)
return inventree_css_static_url
@register.simple_tag()
def authorized_owners(group):
""" Return authorized owners """
owners = []
try:
for owner in group.get_users(include_group=True):
owners.append(owner.owner)
except AttributeError:
# group is None
pass
except TypeError:
# group.get_users returns None
pass
return owners

View File

@ -9,12 +9,15 @@
{% include "stock/tabs.html" with tab="tracking" %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% endif %}
<h4>{% trans "Stock Tracking Information" %}</h4>
<hr>
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and item.owner == user %}
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners %}
{% if roles.stock.change and not item.is_building %}
<div id='table-toolbar'>
<div class='btn-group'>

View File

@ -16,6 +16,15 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% include 'stock/loc_link.html' with location=item.location %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% if not user in owners and not user.is_superuser %}
<div class='alert alert-block alert-info'>
{% trans "You are not the owner of this item. This stock item cannot be edited." %}<br>
</div>
{% endif %}
{% endif %}
{% if item.is_building %}
<div class='alert alert-block alert-info'>
@ -31,12 +40,6 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
</div>
{% endif %}
{% if owner_control.value == "True" and not item.owner == user and not user.is_superuser %}
<div class='alert alert-block alert-info'>
{% trans "You are not the owner of this item. This stock item cannot be edited." %}<br>
</div>
{% endif %}
{% if item.hasRequiredTests and not item.passedAllRequiredTests %}
<div class='alert alert-block alert-danger'>
{% trans "This stock item has not passed all required tests" %}
@ -78,6 +81,9 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% block page_data %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% endif %}
<h3>
{% trans "Stock Item" %}
@ -144,7 +150,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% endif %}
<!-- Stock adjustment menu -->
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and item.owner == user or user.is_superuser %}
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners or user.is_superuser %}
{% if roles.stock.change and not item.is_building %}
<div class='btn-group'>
<button id='stock-actions' title='{% trans "Stock adjustment actions" %}' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><span class='fas fa-boxes'></span> <span class='caret'></span></button>

View File

@ -5,11 +5,14 @@
{% block content %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners location.owner as owners %}
{% if location and owner_control.value == "True" and not location.owner in user.groups.all and not user.is_superuser %}
<div class='alert alert-block alert-info'>
{% trans "You are not in the list of owners of this location. This stock location cannot be edited." %}<br>
</div>
{% if location and not user in owners and not user.is_superuser %}
<div class='alert alert-block alert-info'>
{% trans "You are not in the list of owners of this location. This stock location cannot be edited." %}<br>
</div>
{% endif %}
{% endif %}
<div class='row'>
@ -27,7 +30,7 @@
<p>{% trans "All stock items" %}</p>
{% endif %}
<div class='btn-group action-buttons' role='group'>
{% if owner_control.value == "False" or owner_control.value == "True" and location.owner in user.groups.all or user.is_superuser or not location %}
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners or user.is_superuser or not location %}
{% if roles.stock.add %}
<button class='btn btn-default' id='location-create' title='{% trans "Create new stock location" %}'>
<span class='fas fa-plus-circle icon-green'/>
@ -45,7 +48,7 @@
</ul>
</div>
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and location.owner in user.groups.all or user.is_superuser %}
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners or user.is_superuser %}
{% if roles.stock.change %}
<div class='btn-group'>
<button id='stock-actions' title='{% trans "Stock actions" %}' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><span class='fas fa-boxes'></span> <span class='caret'></span></button>

View File

@ -166,13 +166,59 @@ class StockLocationEdit(AjaxUpdateView):
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if stock_ownership_control:
if self.object.get_children():
for child in self.object.get_children():
child.owner = self.object.owner
child.save()
authorized_owners = self.object.owner.get_users()
print(f'{authorized_owners=}')
# Update children locations
children_locations = self.object.get_children()
for child in children_locations:
# Check if current owner is subset of new owner
if child.owner and authorized_owners:
if child.owner in authorized_owners:
continue
child.owner = self.object.owner
child.save()
# Update stock items
stock_items = self.object.get_stock_items()
print(f'{stock_items=}')
for stock_item in stock_items:
# Check if current owner is subset of new owner
if stock_item.owner and authorized_owners:
if stock_item.owner in authorized_owners:
print(f'{stock_item.owner} is authorized')
continue
print(f'Updating stock item {stock_item} owner')
stock_item.owner = self.object.owner
stock_item.save()
return self.object
def validate(self, item, form):
""" Check that owner is set if stock ownership control is enabled """
parent = form.cleaned_data.get('parent', None)
owner = form.cleaned_data.get('owner', None)
# Is ownership control enabled?
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if stock_ownership_control:
if not owner and not self.request.user.is_superuser:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
else:
try:
if parent.owner:
if parent.owner != owner:
error = f'Owner requires to be equivalent to parent\'s owner ({parent.owner})'
form.add_error('owner', error)
except AttributeError:
# No parent
pass
class StockLocationQRCode(QRCodeView):
""" View for displaying a QR code for a StockLocation object """
@ -1288,6 +1334,18 @@ class StockAdjust(AjaxView, FormMixin):
count += 1
# Is ownership control enabled?
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if stock_ownership_control:
# Fetch destination owner
destination_owner = destination.owner
if destination_owner:
# Update owner
item.owner = destination_owner
item.save()
if count == 0:
return _('No items were moved')
@ -1361,12 +1419,18 @@ class StockItemEdit(AjaxUpdateView):
if not stock_ownership_control:
form.fields['owner'].widget = HiddenInput()
else:
location_owner = location.owner
try:
location_owner = location.owner
except AttributeError:
location_owner = None
# Check if location has owner
if location_owner:
form.fields['owner'].initial = location_owner
# Check location owner type and filter
if type(location_owner.owner) is Group:
queryset = location_owner.get_users()
queryset = location_owner.get_users(include_group=True)
if self.request.user in queryset:
form.fields['owner'].initial = self.request.user
form.fields['owner'].queryset = queryset
@ -1374,6 +1438,25 @@ class StockItemEdit(AjaxUpdateView):
form.fields['owner'].disabled = True
form.fields['owner'].initial = location_owner
try:
item_owner = item.owner
except AttributeError:
item_owner = None
# Check if item has owner
if item_owner:
form.fields['owner'].initial = item_owner
# Check location owner type and filter
if type(item_owner.owner) is Group:
queryset = item_owner.get_users(include_group=True)
if self.request.user in queryset:
form.fields['owner'].initial = self.request.user
form.fields['owner'].queryset = queryset
elif type(item_owner.owner) is User:
form.fields['owner'].disabled = True
form.fields['owner'].initial = item_owner
return form
def validate(self, item, form):
@ -1384,8 +1467,9 @@ class StockItemEdit(AjaxUpdateView):
# Is ownership control enabled?
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if not owner and stock_ownership_control:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
if stock_ownership_control:
if not owner and not self.request.user.is_superuser:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
class StockItemConvert(AjaxUpdateView):
@ -1495,7 +1579,7 @@ class StockLocationCreate(AjaxCreateView):
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if stock_ownership_control:
if not owner:
if not owner and not self.request.user.is_superuser:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
else:
try:
@ -1716,7 +1800,11 @@ class StockItemCreate(AjaxCreateView):
if not stock_ownership_control:
form.fields['owner'].widget = HiddenInput()
else:
location_owner = location.owner
try:
location_owner = location.owner
except AttributeError:
location_owner = None
if location_owner:
# Check location owner type and filter
if type(location_owner.owner) is Group:
@ -1848,7 +1936,7 @@ class StockItemCreate(AjaxCreateView):
if stock_ownership_control:
# Check if owner is set
if not owner:
if not owner and not self.request.user.is_superuser:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
return

View File

@ -2,6 +2,9 @@
{% load inventree_extras %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners location.owner as owners %}
{% endif %}
<div id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'>
@ -12,7 +15,7 @@
{% if read_only %}
{% else %}
<!-- Check permissions and owner -->
{% if owner_control.value == "False" or owner_control.value == "True" and location.owner in user.groups.all or user.is_superuser %}
{% if owner_control.value == "False" or owner_control.value == "True" and user in owners or user.is_superuser %}
{% if roles.stock.add %}
<button class="btn btn-success" id='item-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Stock Item" %}

View File

@ -3,7 +3,7 @@
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db.models import UniqueConstraint
from django.db.models import UniqueConstraint, Q
from django.db.utils import IntegrityError
from django.db import models
from django.utils.translation import gettext_lazy as _
@ -112,6 +112,7 @@ class RuleSet(models.Model):
'report_reportasset',
'report_testreport',
'part_partstar',
'users_owner',
# Third-party tables
'error_report_error',
@ -433,14 +434,23 @@ class Owner(models.Model):
except IntegrityError:
return None
def get_users(self):
def get_users(self, include_group=False):
owner_users = None
if type(self.owner) is Group:
users = User.objects.filter(groups__name=self.owner.name)
owner_users = Owner.objects.filter(owner_id__in=users,
owner_type=ContentType.objects.get_for_model(User).id)
if include_group:
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(User).id) | \
Q(owner_id=self.owner.id, owner_type=ContentType.objects.get_for_model(Group).id)
else:
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(User).id)
owner_users = Owner.objects.filter(query)
elif type(self.owner) is User:
owner_users = [self]
return owner_users