mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Updated templates and a lot of manual testing
This commit is contained in:
parent
9eace09e0e
commit
b6135fda74
@ -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
|
||||
|
@ -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'>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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" %}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user