From 92cbd43f0fc1a835d96353d5db6170de3dade64c Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 20 Apr 2017 22:20:41 +1000 Subject: [PATCH 1/4] Code cleanup --- InvenTree/stock/models.py | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 877661dd7f..77ff41d75a 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -78,27 +78,6 @@ class StockItem(models.Model): self.stocktake_date = datetime.now().date() self.save() - def take_stock(self, amount): - """ Take items from stock - This function can be called by initiating a ProjectRun, - or by manually taking the items from the stock location - """ - - if self.infinite: - return - - amount = int(amount) - if amount < 0: - raise ValueError("Stock amount must be positive") - - q = self.quantity - amount - - if q < 0: - q = 0 - - self.quantity = q - self.save() - def add_stock(self, amount): """ Add items to stock This function can be called by initiating a ProjectRun, @@ -119,6 +98,9 @@ class StockItem(models.Model): self.quantity = q self.save() + def take_stock(self, amount): + self.add_stock(-amount) + def __str__(self): return "{n} x {part} @ {loc}".format( n=self.quantity, From 4777b020802054e068accc782f75cb39f5006dbc Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 20 Apr 2017 22:40:59 +1000 Subject: [PATCH 2/4] Added User API and serializer --- InvenTree/InvenTree/urls.py | 6 ++++++ InvenTree/stock/models.py | 5 ++++- InvenTree/stock/serializers.py | 1 + InvenTree/stock/views.py | 2 +- InvenTree/users/__init__.py | 0 InvenTree/users/admin.py | 6 ++++++ InvenTree/users/apps.py | 8 ++++++++ InvenTree/users/models.py | 6 ++++++ InvenTree/users/serializers.py | 15 +++++++++++++++ InvenTree/users/tests.py | 6 ++++++ InvenTree/users/urls.py | 9 +++++++++ InvenTree/users/views.py | 17 +++++++++++++++++ 12 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 InvenTree/users/__init__.py create mode 100644 InvenTree/users/admin.py create mode 100644 InvenTree/users/apps.py create mode 100644 InvenTree/users/models.py create mode 100644 InvenTree/users/serializers.py create mode 100644 InvenTree/users/tests.py create mode 100644 InvenTree/users/urls.py create mode 100644 InvenTree/users/views.py diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index e50470dc1c..466bf2014f 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -8,9 +8,12 @@ from stock.urls import stock_urls, stock_loc_urls, stock_track_urls from project.urls import prj_urls, prj_part_urls, prj_cat_urls, prj_run_urls from supplier.urls import cust_urls, manu_urls, supplier_part_urls, price_break_urls, supplier_urls from track.urls import unique_urls, part_track_urls +from users.urls import user_urls admin.site.site_header = "InvenTree Admin" + + apipatterns = [ # Stock URLs @@ -40,6 +43,9 @@ apipatterns = [ url(r'^project-category/', include(prj_cat_urls)), url(r'^project-part/', include(prj_part_urls)), url(r'^project-run/', include(prj_run_urls)), + + # User URLs + url(r'^user/', include(user_urls)), ] urlpatterns = [ diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index 77ff41d75a..c4be02eb63 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.utils.translation import ugettext as _ from django.db import models from django.core.validators import MinValueValidator +from django.contrib.auth.models import User from supplier.models import SupplierPart from part.models import Part @@ -29,6 +30,7 @@ class StockItem(models.Model): # last time the stock was checked / counted stocktake_date = models.DateField(blank=True, null=True) + stocktake_user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True) review_needed = models.BooleanField(default=False) @@ -63,7 +65,7 @@ class StockItem(models.Model): infinite = models.BooleanField(default=False) - def stocktake(self, count): + def stocktake(self, count, user): """ Perform item stocktake. When the quantity of an item is counted, record the date of stocktake @@ -76,6 +78,7 @@ class StockItem(models.Model): self.quantity = count self.stocktake_date = datetime.now().date() + self.stocktake_user = user self.save() def add_stock(self, amount): diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index e73be8531b..fc0c6979fe 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -18,6 +18,7 @@ class StockItemSerializer(serializers.HyperlinkedModelSerializer): 'notes', 'updated', 'stocktake_date', + 'stocktake_user', 'review_needed', 'expected_arrival') diff --git a/InvenTree/stock/views.py b/InvenTree/stock/views.py index 26d6aa1e74..4dab2f4546 100644 --- a/InvenTree/stock/views.py +++ b/InvenTree/stock/views.py @@ -62,7 +62,7 @@ class StockStocktakeEndpoint(generics.UpdateAPIView): def update(self, request, *args, **kwargs): object = self.get_object() - object.stocktake(request.data['quantity']) + object.stocktake(request.data['quantity'], request.user) serializer = self.get_serializer(object) diff --git a/InvenTree/users/__init__.py b/InvenTree/users/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/InvenTree/users/admin.py b/InvenTree/users/admin.py new file mode 100644 index 0000000000..13be29d96f --- /dev/null +++ b/InvenTree/users/admin.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.contrib import admin + +# Register your models here. diff --git a/InvenTree/users/apps.py b/InvenTree/users/apps.py new file mode 100644 index 0000000000..251989770b --- /dev/null +++ b/InvenTree/users/apps.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class UsersConfig(AppConfig): + name = 'users' diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py new file mode 100644 index 0000000000..1dfab76043 --- /dev/null +++ b/InvenTree/users/models.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models + +# Create your models here. diff --git a/InvenTree/users/serializers.py b/InvenTree/users/serializers.py new file mode 100644 index 0000000000..2bbb8adcca --- /dev/null +++ b/InvenTree/users/serializers.py @@ -0,0 +1,15 @@ +from rest_framework import serializers +from django.contrib.auth.models import User + + +class UserSerializer(serializers.HyperlinkedModelSerializer): + """ Serializer for a User + """ + + class Meta: + model = User + fields = ('username', + 'first_name', + 'last_name', + 'email',) + diff --git a/InvenTree/users/tests.py b/InvenTree/users/tests.py new file mode 100644 index 0000000000..5982e6bcd2 --- /dev/null +++ b/InvenTree/users/tests.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.test import TestCase + +# Create your tests here. diff --git a/InvenTree/users/urls.py b/InvenTree/users/urls.py new file mode 100644 index 0000000000..92e2726535 --- /dev/null +++ b/InvenTree/users/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import url, include + +from . import views + +user_urls = [ + url(r'^(?P[0-9]+)/?$', views.UserDetail.as_view(), name='user-detail'), + + url(r'^$', views.UserList.as_view()), +] diff --git a/InvenTree/users/views.py b/InvenTree/users/views.py new file mode 100644 index 0000000000..ba7e910ddc --- /dev/null +++ b/InvenTree/users/views.py @@ -0,0 +1,17 @@ +from rest_framework import generics, permissions, response +from django.contrib.auth.models import User +from .serializers import UserSerializer + + +class UserDetail(generics.RetrieveAPIView): + + queryset = User.objects.all() + serializer_class = UserSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) + + +class UserList(generics.ListAPIView): + + queryset = User.objects.all() + serializer_class = UserSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) From db45e3625f86b1fec6cf27de0dc6514604f34b1a Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 20 Apr 2017 22:45:18 +1000 Subject: [PATCH 3/4] Category validation errors --- InvenTree/InvenTree/models.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/InvenTree/InvenTree/models.py b/InvenTree/InvenTree/models.py index 35ed5ccc0c..acfdad80fc 100644 --- a/InvenTree/InvenTree/models.py +++ b/InvenTree/InvenTree/models.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.db import models from django.contrib.contenttypes.models import ContentType +from rest_framework.exceptions import ValidationError class Company(models.Model): @@ -150,7 +151,7 @@ class InvenTreeTree(models.Model): pass # Parent cannot be set to same ID (this would cause looping) elif val == self.id: - return + raise ValidationError("Category cannot set itself as parent") # Null parent is OK elif val is None: pass @@ -158,7 +159,7 @@ class InvenTreeTree(models.Model): else: kids = self.getUniqueChildren() if val in kids: - return + raise ValidationError("Category cannot set a child as parent") # Prohibit certain characters from tree node names elif attrname == 'name': From 76b086aab8af040eb2781beb612ff6f5458ee107 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Thu, 20 Apr 2017 22:53:28 +1000 Subject: [PATCH 4/4] Style fixes --- InvenTree/InvenTree/urls.py | 2 -- InvenTree/users/admin.py | 7 ++----- InvenTree/users/models.py | 5 ----- InvenTree/users/serializers.py | 1 - InvenTree/users/tests.py | 6 ++---- InvenTree/users/urls.py | 2 +- InvenTree/users/views.py | 2 +- 7 files changed, 6 insertions(+), 19 deletions(-) diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index 466bf2014f..a81134e48f 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -12,8 +12,6 @@ from users.urls import user_urls admin.site.site_header = "InvenTree Admin" - - apipatterns = [ # Stock URLs diff --git a/InvenTree/users/admin.py b/InvenTree/users/admin.py index 13be29d96f..b12fa73f94 100644 --- a/InvenTree/users/admin.py +++ b/InvenTree/users/admin.py @@ -1,6 +1,3 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.contrib import admin - -# Register your models here. +# from __future__ import unicode_literals +# from django.contrib import admin diff --git a/InvenTree/users/models.py b/InvenTree/users/models.py index 1dfab76043..40a96afc6f 100644 --- a/InvenTree/users/models.py +++ b/InvenTree/users/models.py @@ -1,6 +1 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models - -# Create your models here. diff --git a/InvenTree/users/serializers.py b/InvenTree/users/serializers.py index 2bbb8adcca..01ce8f44b3 100644 --- a/InvenTree/users/serializers.py +++ b/InvenTree/users/serializers.py @@ -12,4 +12,3 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): 'first_name', 'last_name', 'email',) - diff --git a/InvenTree/users/tests.py b/InvenTree/users/tests.py index 5982e6bcd2..57c7c1fe6b 100644 --- a/InvenTree/users/tests.py +++ b/InvenTree/users/tests.py @@ -1,6 +1,4 @@ # -*- coding: utf-8 -*- -from __future__ import unicode_literals +# from __future__ import unicode_literals -from django.test import TestCase - -# Create your tests here. +# from django.test import TestCase diff --git a/InvenTree/users/urls.py b/InvenTree/users/urls.py index 92e2726535..046cab9428 100644 --- a/InvenTree/users/urls.py +++ b/InvenTree/users/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url, include +from django.conf.urls import url from . import views diff --git a/InvenTree/users/views.py b/InvenTree/users/views.py index ba7e910ddc..20fee70caa 100644 --- a/InvenTree/users/views.py +++ b/InvenTree/users/views.py @@ -1,4 +1,4 @@ -from rest_framework import generics, permissions, response +from rest_framework import generics, permissions from django.contrib.auth.models import User from .serializers import UserSerializer