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) inventree_css_static_url = os.path.join(settings.STATIC_URL, inventree_css_sheet)
return inventree_css_static_url 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" %} {% include "stock/tabs.html" with tab="tracking" %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} {% 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> <h4>{% trans "Stock Tracking Information" %}</h4>
<hr> <hr>
<!-- Check permissions and owner --> <!-- 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 %} {% if roles.stock.change and not item.is_building %}
<div id='table-toolbar'> <div id='table-toolbar'>
<div class='btn-group'> <div class='btn-group'>

View File

@ -16,6 +16,15 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% include 'stock/loc_link.html' with location=item.location %} {% include 'stock/loc_link.html' with location=item.location %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} {% 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 %} {% if item.is_building %}
<div class='alert alert-block alert-info'> <div class='alert alert-block alert-info'>
@ -31,12 +40,6 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
</div> </div>
{% endif %} {% 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 %} {% if item.hasRequiredTests and not item.passedAllRequiredTests %}
<div class='alert alert-block alert-danger'> <div class='alert alert-block alert-danger'>
{% trans "This stock item has not passed all required tests" %} {% trans "This stock item has not passed all required tests" %}
@ -78,6 +81,9 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% block page_data %} {% block page_data %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} {% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %}
{% if owner_control.value == "True" %}
{% authorized_owners item.owner as owners %}
{% endif %}
<h3> <h3>
{% trans "Stock Item" %} {% trans "Stock Item" %}
@ -144,7 +150,7 @@ InvenTree | {% trans "Stock Item" %} - {{ item }}
{% endif %} {% endif %}
<!-- Stock adjustment menu --> <!-- Stock adjustment menu -->
<!-- Check permissions and owner --> <!-- 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 %} {% if roles.stock.change and not item.is_building %}
<div class='btn-group'> <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> <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 %} {% block content %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} {% 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 %} {% if location and not user in owners and not user.is_superuser %}
<div class='alert alert-block alert-info'> <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> {% trans "You are not in the list of owners of this location. This stock location cannot be edited." %}<br>
</div> </div>
{% endif %}
{% endif %} {% endif %}
<div class='row'> <div class='row'>
@ -27,7 +30,7 @@
<p>{% trans "All stock items" %}</p> <p>{% trans "All stock items" %}</p>
{% endif %} {% endif %}
<div class='btn-group action-buttons' role='group'> <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 %} {% if roles.stock.add %}
<button class='btn btn-default' id='location-create' title='{% trans "Create new stock location" %}'> <button class='btn btn-default' id='location-create' title='{% trans "Create new stock location" %}'>
<span class='fas fa-plus-circle icon-green'/> <span class='fas fa-plus-circle icon-green'/>
@ -45,7 +48,7 @@
</ul> </ul>
</div> </div>
<!-- Check permissions and owner --> <!-- 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 %} {% if roles.stock.change %}
<div class='btn-group'> <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> <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') stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if stock_ownership_control: if stock_ownership_control:
if self.object.get_children(): authorized_owners = self.object.owner.get_users()
for child in self.object.get_children(): print(f'{authorized_owners=}')
child.owner = self.object.owner
child.save() # 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 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): class StockLocationQRCode(QRCodeView):
""" View for displaying a QR code for a StockLocation object """ """ View for displaying a QR code for a StockLocation object """
@ -1288,6 +1334,18 @@ class StockAdjust(AjaxView, FormMixin):
count += 1 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: if count == 0:
return _('No items were moved') return _('No items were moved')
@ -1361,12 +1419,18 @@ class StockItemEdit(AjaxUpdateView):
if not stock_ownership_control: if not stock_ownership_control:
form.fields['owner'].widget = HiddenInput() form.fields['owner'].widget = HiddenInput()
else: else:
location_owner = location.owner try:
location_owner = location.owner
except AttributeError:
location_owner = None
# Check if location has owner # Check if location has owner
if location_owner: if location_owner:
form.fields['owner'].initial = location_owner
# Check location owner type and filter # Check location owner type and filter
if type(location_owner.owner) is Group: 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: if self.request.user in queryset:
form.fields['owner'].initial = self.request.user form.fields['owner'].initial = self.request.user
form.fields['owner'].queryset = queryset form.fields['owner'].queryset = queryset
@ -1374,6 +1438,25 @@ class StockItemEdit(AjaxUpdateView):
form.fields['owner'].disabled = True form.fields['owner'].disabled = True
form.fields['owner'].initial = location_owner 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 return form
def validate(self, item, form): def validate(self, item, form):
@ -1384,8 +1467,9 @@ class StockItemEdit(AjaxUpdateView):
# Is ownership control enabled? # Is ownership control enabled?
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL') stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if not owner and stock_ownership_control: if stock_ownership_control:
form.add_error('owner', _('Owner is required (ownership control is enabled)')) if not owner and not self.request.user.is_superuser:
form.add_error('owner', _('Owner is required (ownership control is enabled)'))
class StockItemConvert(AjaxUpdateView): class StockItemConvert(AjaxUpdateView):
@ -1495,7 +1579,7 @@ class StockLocationCreate(AjaxCreateView):
stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL') stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
if 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)')) form.add_error('owner', _('Owner is required (ownership control is enabled)'))
else: else:
try: try:
@ -1716,7 +1800,11 @@ class StockItemCreate(AjaxCreateView):
if not stock_ownership_control: if not stock_ownership_control:
form.fields['owner'].widget = HiddenInput() form.fields['owner'].widget = HiddenInput()
else: else:
location_owner = location.owner try:
location_owner = location.owner
except AttributeError:
location_owner = None
if location_owner: if location_owner:
# Check location owner type and filter # Check location owner type and filter
if type(location_owner.owner) is Group: if type(location_owner.owner) is Group:
@ -1848,7 +1936,7 @@ class StockItemCreate(AjaxCreateView):
if stock_ownership_control: if stock_ownership_control:
# Check if owner is set # 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)')) form.add_error('owner', _('Owner is required (ownership control is enabled)'))
return return

View File

@ -2,6 +2,9 @@
{% load inventree_extras %} {% load inventree_extras %}
{% setting_object 'STOCK_OWNERSHIP_CONTROL' as owner_control %} {% 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 id='button-toolbar'>
<div class='button-toolbar container-fluid' style='float: right;'> <div class='button-toolbar container-fluid' style='float: right;'>
@ -12,7 +15,7 @@
{% if read_only %} {% if read_only %}
{% else %} {% else %}
<!-- Check permissions and owner --> <!-- 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 %} {% if roles.stock.add %}
<button class="btn btn-success" id='item-create'> <button class="btn btn-success" id='item-create'>
<span class='fas fa-plus-circle'></span> {% trans "New Stock Item" %} <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.auth.models import User, Group, Permission
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType 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.utils import IntegrityError
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -112,6 +112,7 @@ class RuleSet(models.Model):
'report_reportasset', 'report_reportasset',
'report_testreport', 'report_testreport',
'part_partstar', 'part_partstar',
'users_owner',
# Third-party tables # Third-party tables
'error_report_error', 'error_report_error',
@ -433,14 +434,23 @@ class Owner(models.Model):
except IntegrityError: except IntegrityError:
return None return None
def get_users(self): def get_users(self, include_group=False):
owner_users = None owner_users = None
if type(self.owner) is Group: if type(self.owner) is Group:
users = User.objects.filter(groups__name=self.owner.name) 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 return owner_users