예제 #1
0
    def update_owners(self):

        from django.contrib.auth import get_user_model
        from django.contrib.auth.models import Group
        from users.models import Owner

        # Create group owners
        for group in Group.objects.all():
            Owner.create(group)

        # Create user owners
        for user in get_user_model().objects.all():
            Owner.create(user)
예제 #2
0
파일: apps.py 프로젝트: inventree/InvenTree
    def update_owners(self):
        """Create an 'owner' object for each user and group instance"""
        from django.contrib.auth import get_user_model
        from django.contrib.auth.models import Group

        from users.models import Owner

        # Create group owners
        for group in Group.objects.all():
            Owner.create(group)

        # Create user owners
        for user in get_user_model().objects.all():
            Owner.create(user)
예제 #3
0
    def test_overdue_notification(self):
        """Test overdue purchase order notification

        Ensure that a notification is sent when a PurchaseOrder becomes overdue
        """
        po = PurchaseOrder.objects.get(pk=1)

        # Created by 'sam'
        po.created_by = get_user_model().objects.get(pk=4)

        # Responsible : 'Engineers' group
        responsible = Owner.create(obj=Group.objects.get(pk=2))
        po.responsible = responsible

        # Target date = yesterday
        po.target_date = datetime.now().date() - timedelta(days=1)
        po.save()

        # Check for overdue purchase orders
        order.tasks.check_overdue_purchase_orders()

        for user_id in [2, 3, 4]:
            messages = common.models.NotificationMessage.objects.filter(
                category='order.overdue_purchase_order',
                user__id=user_id,
            )

            self.assertTrue(messages.exists())

            msg = messages.first()

            self.assertEqual(msg.target_object_id, 1)
            self.assertEqual(msg.name, 'Overdue Purchase Order')
예제 #4
0
    def get_form(self):
        """ Customize form data for StockLocation editing.

        Limit the choices for 'parent' field to those which make sense.
        If ownership control is enabled and location has parent, disable owner field.
        """

        form = super(AjaxUpdateView, self).get_form()

        location = self.get_object()

        # Remove any invalid choices for the 'parent' field
        parent_choices = StockLocation.objects.all()
        parent_choices = parent_choices.exclude(
            id__in=location.getUniqueChildren())

        form.fields['parent'].queryset = parent_choices

        # Is ownership control enabled?
        stock_ownership_control = InvenTreeSetting.get_setting(
            'STOCK_OWNERSHIP_CONTROL')

        if not stock_ownership_control:
            # Hide owner field
            form.fields['owner'].widget = HiddenInput()
        else:
            # Get location's owner
            location_owner = location.owner

            if location_owner:
                if location.parent:
                    try:
                        # If location has parent and owner: automatically select parent's owner
                        parent_owner = location.parent.owner
                        form.fields['owner'].initial = parent_owner
                    except AttributeError:
                        pass
                else:
                    # If current owner exists: automatically select it
                    form.fields['owner'].initial = location_owner

                # Update queryset or disable field (only if not admin)
                if not self.request.user.is_superuser:
                    if type(location_owner.owner) is Group:
                        user_as_owner = Owner.get_owner(self.request.user)
                        queryset = location_owner.get_related_owners(
                            include_group=True)

                        if user_as_owner not in queryset:
                            # Only owners or admin can change current owner
                            form.fields['owner'].disabled = True
                        else:
                            form.fields['owner'].queryset = queryset

        return form
예제 #5
0
파일: tests.py 프로젝트: matmair/InvenTree
    def test_owner(self):

        # Check that owner was created for user
        user_as_owner = Owner.get_owner(self.user)
        self.assertEqual(type(user_as_owner), Owner)

        # Check that owner was created for group
        group_as_owner = Owner.get_owner(self.group)
        self.assertEqual(type(group_as_owner), Owner)

        # Check name
        self.assertEqual(str(user_as_owner), 'testuser (user)')

        # Get related owners (user + group)
        related_owners = group_as_owner.get_related_owners(include_group=True)
        self.assertTrue(user_as_owner in related_owners)
        self.assertTrue(group_as_owner in related_owners)

        # Get related owners (only user)
        related_owners = group_as_owner.get_related_owners(include_group=False)
        self.assertTrue(user_as_owner in related_owners)
        self.assertFalse(group_as_owner in related_owners)

        # Get related owners on user
        related_owners = user_as_owner.get_related_owners()
        self.assertEqual(related_owners, [user_as_owner])

        # Check owner matching
        owners = Owner.get_owners_matching_user(self.user)
        self.assertEqual(owners, [user_as_owner, group_as_owner])

        # Delete user and verify owner was deleted too
        self.user.delete()
        user_as_owner = Owner.get_owner(self.user)
        self.assertEqual(user_as_owner, None)

        # Delete group and verify owner was deleted too
        self.group.delete()
        group_as_owner = Owner.get_owner(self.group)
        self.assertEqual(group_as_owner, None)
예제 #6
0
    def filter_assigned_to_me(self, queryset, name, value):
        """Filter by orders which are assigned to the current user."""
        value = str2bool(value)

        # Work out who "me" is!
        owners = Owner.get_owners_matching_user(self.request.user)

        if value:
            queryset = queryset.filter(responsible__in=owners)
        else:
            queryset = queryset.exclude(responsible__in=owners)

        return queryset
예제 #7
0
    def test_overdue_notification(self):
        """Test overdue sales order notification"""

        self.order.created_by = get_user_model().objects.get(pk=3)
        self.order.responsible = Owner.create(obj=Group.objects.get(pk=2))
        self.order.target_date = datetime.now().date() - timedelta(days=1)
        self.order.save()

        # Check for overdue sales orders
        order.tasks.check_overdue_sales_orders()

        messages = NotificationMessage.objects.filter(
            category='order.overdue_sales_order', )

        self.assertEqual(len(messages), 2)
예제 #8
0
    def test_owner(self):

        # Check that owner was created for user
        user_as_owner = Owner.get_owner(self.user)
        self.assertEqual(type(user_as_owner), Owner)

        # Check that owner was created for group
        group_as_owner = Owner.get_owner(self.group)
        self.assertEqual(type(group_as_owner), Owner)

        # Get related owners (user + group)
        related_owners = group_as_owner.get_related_owners(include_group=True)
        self.assertTrue(user_as_owner in related_owners)
        self.assertTrue(group_as_owner in related_owners)

        # Delete user and verify owner was deleted too
        self.user.delete()
        user_as_owner = Owner.get_owner(self.user)
        self.assertEqual(user_as_owner, None)

        # Delete group and verify owner was deleted too
        self.group.delete()
        group_as_owner = Owner.get_owner(self.group)
        self.assertEqual(group_as_owner, None)
예제 #9
0
    def test_new_build_notification(self):
        """Test that a notification is sent when a new build is created"""

        Build.objects.create(
            reference='BO-9999',
            title='Some new build',
            part=self.assembly,
            quantity=5,
            issued_by=get_user_model().objects.get(pk=2),
            responsible=Owner.create(obj=Group.objects.get(pk=3)))

        # Two notifications should have been sent
        messages = common.models.NotificationMessage.objects.filter(
            category='build.new_build', )

        self.assertEqual(messages.count(), 2)

        self.assertFalse(messages.filter(user__pk=2).exists())

        self.assertTrue(messages.filter(user__pk=3).exists())
        self.assertTrue(messages.filter(user__pk=4).exists())
예제 #10
0
    def test_new_so_notification(self):
        """Test that a notification is sent when a new SalesOrder is created.

        - The responsible user should receive a notification
        - The creating user should *not* receive a notification
        """

        SalesOrder.objects.create(
            customer=self.customer,
            reference='1234567',
            created_by=get_user_model().objects.get(pk=3),
            responsible=Owner.create(obj=Group.objects.get(pk=3)))

        messages = NotificationMessage.objects.filter(
            category='order.new_salesorder', )

        # A notification should have been generated for user 4 (who is a member of group 3)
        self.assertTrue(messages.filter(user__pk=4).exists())

        # However *no* notification should have been generated for the creating user
        self.assertFalse(messages.filter(user__pk=3).exists())
예제 #11
0
    def test_new_po_notification(self):
        """Test that a notification is sent when a new PurchaseOrder is created

        - The responsible user(s) should receive a notification
        - The creating user should *not* receive a notification
        """

        PurchaseOrder.objects.create(
            supplier=Company.objects.get(pk=1),
            reference='XYZABC',
            created_by=get_user_model().objects.get(pk=3),
            responsible=Owner.create(obj=get_user_model().objects.get(pk=4)),
        )

        messages = common.models.NotificationMessage.objects.filter(
            category='order.new_purchaseorder', )

        self.assertEqual(messages.count(), 1)

        # A notification should have been generated for user 4 (who is a member of group 3)
        self.assertTrue(messages.filter(user__pk=4).exists())

        # However *no* notification should have been generated for the creating user
        self.assertFalse(messages.filter(user__pk=3).exists())
예제 #12
0
    def test_owner_control(self):
        # Test stock location and item ownership
        from .models import StockLocation, StockItem
        from users.models import Owner

        user_group = self.user.groups.all()[0]
        user_group_owner = Owner.get_owner(user_group)
        new_user_group = self.new_user.groups.all()[0]
        new_user_group_owner = Owner.get_owner(new_user_group)

        user_as_owner = Owner.get_owner(self.user)
        new_user_as_owner = Owner.get_owner(self.new_user)

        test_location_id = 4
        test_item_id = 11

        # Enable ownership control
        self.enable_ownership()

        # Set ownership on existing location
        response = self.client.post(reverse('stock-location-edit',
                                            args=(test_location_id, )), {
                                                'name': 'Office',
                                                'owner': user_group_owner.pk
                                            },
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Set ownership on existing item (and change location)
        response = self.client.post(reverse('stock-item-edit',
                                            args=(test_item_id, )), {
                                                'part': 1,
                                                'status': StockStatus.OK,
                                                'owner': user_as_owner.pk
                                            },
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Logout
        self.client.logout()

        # Login with new user
        self.client.login(username='******', password='******')

        # Test location edit
        response = self.client.post(reverse('stock-location-edit',
                                            args=(test_location_id, )),
                                    {
                                        'name': 'Office',
                                        'owner': new_user_group_owner.pk
                                    },
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        # Make sure the location's owner is unchanged
        location = StockLocation.objects.get(pk=test_location_id)
        self.assertEqual(location.owner, user_group_owner)

        # Test item edit
        response = self.client.post(reverse('stock-item-edit',
                                            args=(test_item_id, )), {
                                                'part': 1,
                                                'status': StockStatus.OK,
                                                'owner': new_user_as_owner.pk
                                            },
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')

        # Make sure the item's owner is unchanged
        item = StockItem.objects.get(pk=test_item_id)
        self.assertEqual(item.owner, user_as_owner)

        # Create new parent location
        parent_location = {
            'name': 'John Desk',
            'description': 'John\'s desk',
            'owner': new_user_group_owner.pk,
        }

        # Create new parent location
        response = self.client.post(reverse('stock-location-create'),
                                    parent_location,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Retrieve created location
        parent_location = StockLocation.objects.get(
            name=parent_location['name'])

        # Create new child location
        new_location = {
            'name': 'Upper Left Drawer',
            'description': 'John\'s desk - Upper left drawer',
        }

        # Try to create new location with neither parent or owner
        response = self.client.post(reverse('stock-location-create'),
                                    new_location,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": false', status_code=200)

        # Try to create new location with invalid owner
        new_location['parent'] = parent_location.id
        new_location['owner'] = user_group_owner.pk
        response = self.client.post(reverse('stock-location-create'),
                                    new_location,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": false', status_code=200)

        # Try to create new location with valid owner
        new_location['owner'] = new_user_group_owner.pk
        response = self.client.post(reverse('stock-location-create'),
                                    new_location,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Retrieve created location
        location_created = StockLocation.objects.get(name=new_location['name'])

        # Create new item
        new_item = {
            'part': 25,
            'location': location_created.pk,
            'quantity': 123,
            'status': StockStatus.OK,
        }

        # Try to create new item with no owner
        response = self.client.post(reverse('stock-item-create'),
                                    new_item,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": false', status_code=200)

        # Try to create new item with invalid owner
        new_item['owner'] = user_as_owner.pk
        response = self.client.post(reverse('stock-item-create'),
                                    new_item,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": false', status_code=200)

        # Try to create new item with valid owner
        new_item['owner'] = new_user_as_owner.pk
        response = self.client.post(reverse('stock-item-create'),
                                    new_item,
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Logout
        self.client.logout()

        # Login with admin
        self.client.login(username='******', password='******')

        # Switch owner of location
        response = self.client.post(reverse('stock-location-edit',
                                            args=(location_created.pk, )), {
                                                'name': new_location['name'],
                                                'owner': user_group_owner.pk
                                            },
                                    HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        self.assertContains(response, '"form_valid": true', status_code=200)

        # Check that owner was updated for item in this location
        stock_item = StockItem.objects.all().last()
        self.assertEqual(stock_item.owner, user_group_owner)
예제 #13
0
파일: views.py 프로젝트: wengtad/InvenTree
    def get_form(self):
        """ Get form for StockItem editing.

        Limit the choices for supplier_part
        """

        form = super(AjaxUpdateView, self).get_form()

        # Hide the "expiry date" field if the feature is not enabled
        if not common.settings.stock_expiry_enabled():
            form.fields['expiry_date'].widget = HiddenInput()

        item = self.get_object()

        # If the part cannot be purchased, hide the supplier_part field
        if not item.part.purchaseable:
            form.fields['supplier_part'].widget = HiddenInput()

            form.fields.pop('purchase_price')
        else:
            query = form.fields['supplier_part'].queryset
            query = query.filter(part=item.part.id)
            form.fields['supplier_part'].queryset = query

        # Hide the serial number field if it is not required
        if not item.part.trackable and not item.serialized:
            form.fields['serial'].widget = HiddenInput()

        location = item.location

        # Is ownership control enabled?
        stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')

        if not stock_ownership_control:
            form.fields['owner'].widget = HiddenInput()
        else:
            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's owner type and filter potential owners
                if type(location_owner.owner) is Group:
                    user_as_owner = Owner.get_owner(self.request.user)
                    queryset = location_owner.get_related_owners(include_group=True)

                    if user_as_owner in queryset:
                        form.fields['owner'].initial = user_as_owner

                    form.fields['owner'].queryset = queryset

                elif type(location_owner.owner) is get_user_model():
                    # If location's owner is a user: automatically set owner field and disable it
                    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 item's owner type and filter potential owners
                if type(item_owner.owner) is Group:
                    user_as_owner = Owner.get_owner(self.request.user)
                    queryset = item_owner.get_related_owners(include_group=True)

                    if user_as_owner in queryset:
                        form.fields['owner'].initial = user_as_owner

                    form.fields['owner'].queryset = queryset

                elif type(item_owner.owner) is get_user_model():
                    # If item's owner is a user: automatically set owner field and disable it
                    form.fields['owner'].disabled = True
                    form.fields['owner'].initial = item_owner

        return form
예제 #14
0
파일: views.py 프로젝트: wengtad/InvenTree
    def get_form(self):
        """ Get form for StockItem creation.
        Overrides the default get_form() method to intelligently limit
        ForeignKey choices based on other selections
        """

        form = super().get_form()

        # Hide the "expiry date" field if the feature is not enabled
        if not common.settings.stock_expiry_enabled():
            form.fields['expiry_date'].widget = HiddenInput()

        part = self.get_part(form=form)

        if part is not None:

            # Add placeholder text for the serial number field
            form.field_placeholder['serial_numbers'] = part.getSerialNumberString()

            form.rebuild_layout()

            if not part.purchaseable:
                form.fields.pop('purchase_price')

            # Hide the 'part' field (as a valid part is selected)
            # form.fields['part'].widget = HiddenInput()

            # Trackable parts get special consideration:
            if part.trackable:
                form.fields['delete_on_deplete'].disabled = True
            else:
                form.fields['serial_numbers'].disabled = True

            # If the part is NOT purchaseable, hide the supplier_part field
            if not part.purchaseable:
                form.fields['supplier_part'].widget = HiddenInput()
            else:
                # Pre-select the allowable SupplierPart options
                parts = form.fields['supplier_part'].queryset
                parts = parts.filter(part=part.id)

                form.fields['supplier_part'].queryset = parts

                # If there is one (and only one) supplier part available, pre-select it
                all_parts = parts.all()

                if len(all_parts) == 1:

                    # TODO - This does NOT work for some reason? Ref build.views.BuildItemCreate
                    form.fields['supplier_part'].initial = all_parts[0].id

        else:
            # No Part has been selected!
            # We must not provide *any* options for SupplierPart
            form.fields['supplier_part'].queryset = SupplierPart.objects.none()

            form.fields['serial_numbers'].disabled = True

        # Otherwise if the user has selected a SupplierPart, we know what Part they meant!
        if form['supplier_part'].value() is not None:
            pass

        location = None
        try:
            loc_id = form['location'].value()
            location = StockLocation.objects.get(pk=loc_id)
        except StockLocation.DoesNotExist:
            pass
        except ValueError:
            pass

        # Is ownership control enabled?
        stock_ownership_control = InvenTreeSetting.get_setting('STOCK_OWNERSHIP_CONTROL')
        if not stock_ownership_control:
            form.fields['owner'].widget = HiddenInput()
        else:
            try:
                location_owner = location.owner
            except AttributeError:
                location_owner = None

            if location_owner:
                # Check location's owner type and filter potential owners
                if type(location_owner.owner) is Group:
                    user_as_owner = Owner.get_owner(self.request.user)
                    queryset = location_owner.get_related_owners()

                    if user_as_owner in queryset:
                        form.fields['owner'].initial = user_as_owner

                    form.fields['owner'].queryset = queryset

                elif type(location_owner.owner) is get_user_model():
                    # If location's owner is a user: automatically set owner field and disable it
                    form.fields['owner'].disabled = True
                    form.fields['owner'].initial = location_owner

        return form