mirror of
https://github.com/inventree/InvenTree.git
synced 2025-05-02 21:38:48 +00:00
commit
ab2e97399a
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
from InvenTree.models import InvenTreeTree
|
from InvenTree.models import InvenTreeTree
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ class Part(models.Model):
|
|||||||
category = models.ForeignKey(PartCategory, on_delete=models.CASCADE)
|
category = models.ForeignKey(PartCategory, on_delete=models.CASCADE)
|
||||||
|
|
||||||
# Minimum "allowed" stock level
|
# Minimum "allowed" stock level
|
||||||
minimum_stock = models.PositiveIntegerField(default=0)
|
minimum_stock = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
# Units of quantity for this part. Default is "pcs"
|
# Units of quantity for this part. Default is "pcs"
|
||||||
units = models.CharField(max_length=20, default="pcs", blank=True)
|
units = models.CharField(max_length=20, default="pcs", blank=True)
|
||||||
@ -112,7 +113,8 @@ class PartParameterTemplate(models.Model):
|
|||||||
|
|
||||||
format = models.PositiveIntegerField(
|
format = models.PositiveIntegerField(
|
||||||
default=PARAM_NUMERIC,
|
default=PARAM_NUMERIC,
|
||||||
choices=PARAM_TYPE_CODES.items())
|
choices=PARAM_TYPE_CODES.items(),
|
||||||
|
validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "{name} ({units})".format(
|
return "{name} ({units})".format(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
||||||
from django_filters import NumberFilter
|
|
||||||
|
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
|
|
||||||
@ -31,8 +30,6 @@ class PartDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
class PartParamFilter(FilterSet):
|
class PartParamFilter(FilterSet):
|
||||||
|
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PartParameter
|
model = PartParameter
|
||||||
fields = ['part']
|
fields = ['part']
|
||||||
@ -75,7 +72,6 @@ class PartParamDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class PartFilter(FilterSet):
|
class PartFilter(FilterSet):
|
||||||
category = NumberFilter(name='category', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Part
|
model = Part
|
||||||
|
@ -5,6 +5,7 @@ from django.db import models
|
|||||||
|
|
||||||
from InvenTree.models import InvenTreeTree
|
from InvenTree.models import InvenTreeTree
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
|
|
||||||
class ProjectCategory(InvenTreeTree):
|
class ProjectCategory(InvenTreeTree):
|
||||||
@ -46,7 +47,7 @@ class ProjectPart(models.Model):
|
|||||||
|
|
||||||
part = models.ForeignKey(Part, on_delete=models.CASCADE)
|
part = models.ForeignKey(Part, on_delete=models.CASCADE)
|
||||||
project = models.ForeignKey(Project, on_delete=models.CASCADE)
|
project = models.ForeignKey(Project, on_delete=models.CASCADE)
|
||||||
quantity = models.PositiveIntegerField(default=1)
|
quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('part', 'project')
|
unique_together = ('part', 'project')
|
||||||
@ -66,7 +67,8 @@ class ProjectPart(models.Model):
|
|||||||
overage = models.FloatField(default=0)
|
overage = models.FloatField(default=0)
|
||||||
overage_type = models.PositiveIntegerField(
|
overage_type = models.PositiveIntegerField(
|
||||||
default=OVERAGE_ABSOLUTE,
|
default=OVERAGE_ABSOLUTE,
|
||||||
choices=OVARAGE_CODES.items())
|
choices=OVARAGE_CODES.items(),
|
||||||
|
validators=[MinValueValidator(0)])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Set if the part is generated by the project,
|
# Set if the part is generated by the project,
|
||||||
@ -89,6 +91,6 @@ class ProjectRun(models.Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
project = models.ForeignKey(Project, on_delete=models.CASCADE)
|
project = models.ForeignKey(Project, on_delete=models.CASCADE)
|
||||||
quantity = models.PositiveIntegerField(default=1)
|
quantity = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
run_date = models.DateField(auto_now_add=True)
|
run_date = models.DateField(auto_now_add=True)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from rest_framework import generics, permissions
|
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
||||||
|
|
||||||
|
from rest_framework import generics, permissions
|
||||||
from InvenTree.models import FilterChildren
|
from InvenTree.models import FilterChildren
|
||||||
from .models import ProjectCategory, Project, ProjectPart
|
from .models import ProjectCategory, Project, ProjectPart
|
||||||
from .serializers import ProjectSerializer
|
from .serializers import ProjectSerializer
|
||||||
@ -26,6 +27,13 @@ class ProjectDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectFilter(FilterSet):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Project
|
||||||
|
fields = ['category']
|
||||||
|
|
||||||
|
|
||||||
class ProjectList(generics.ListCreateAPIView):
|
class ProjectList(generics.ListCreateAPIView):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -38,19 +46,11 @@ class ProjectList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_queryset(self):
|
queryset = Project.objects.all()
|
||||||
projects = Project.objects.all()
|
|
||||||
params = self.request.query_params
|
|
||||||
|
|
||||||
cat_id = params.get('category', None)
|
|
||||||
|
|
||||||
if cat_id:
|
|
||||||
projects = projects.filter(category=cat_id)
|
|
||||||
|
|
||||||
return projects
|
|
||||||
|
|
||||||
serializer_class = ProjectSerializer
|
serializer_class = ProjectSerializer
|
||||||
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
|
||||||
|
filter_backends = (DjangoFilterBackend,)
|
||||||
|
filter_class = ProjectFilter
|
||||||
|
|
||||||
|
|
||||||
class ProjectCategoryDetail(generics.RetrieveUpdateAPIView):
|
class ProjectCategoryDetail(generics.RetrieveUpdateAPIView):
|
||||||
@ -136,7 +136,7 @@ class ProjectPartDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
delete:
|
delete:
|
||||||
Remove a ProjectPart
|
Remove a ProjectPart
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
queryset = ProjectPart.objects.all()
|
queryset = ProjectPart.objects.all()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
from supplier.models import SupplierPart
|
from supplier.models import SupplierPart
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
@ -21,7 +22,7 @@ class StockItem(models.Model):
|
|||||||
part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='locations')
|
part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='locations')
|
||||||
supplier_part = models.ForeignKey(SupplierPart, blank=True, null=True, on_delete=models.SET_NULL)
|
supplier_part = models.ForeignKey(SupplierPart, blank=True, null=True, on_delete=models.SET_NULL)
|
||||||
location = models.ForeignKey(StockLocation, on_delete=models.CASCADE)
|
location = models.ForeignKey(StockLocation, on_delete=models.CASCADE)
|
||||||
quantity = models.PositiveIntegerField()
|
quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)])
|
||||||
updated = models.DateField(auto_now=True)
|
updated = models.DateField(auto_now=True)
|
||||||
|
|
||||||
# last time the stock was checked / counted
|
# last time the stock was checked / counted
|
||||||
@ -50,7 +51,8 @@ class StockItem(models.Model):
|
|||||||
|
|
||||||
status = models.PositiveIntegerField(
|
status = models.PositiveIntegerField(
|
||||||
default=ITEM_IN_STOCK,
|
default=ITEM_IN_STOCK,
|
||||||
choices=ITEM_STATUS_CODES.items())
|
choices=ITEM_STATUS_CODES.items(),
|
||||||
|
validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
notes = models.CharField(max_length=100, blank=True)
|
notes = models.CharField(max_length=100, blank=True)
|
||||||
|
|
||||||
@ -73,5 +75,4 @@ class StockTracking(models.Model):
|
|||||||
|
|
||||||
item = models.ForeignKey(StockItem, on_delete=models.CASCADE, related_name='tracking')
|
item = models.ForeignKey(StockItem, on_delete=models.CASCADE, related_name='tracking')
|
||||||
quantity = models.IntegerField()
|
quantity = models.IntegerField()
|
||||||
pending = models.BooleanField(default=False)
|
|
||||||
when = models.DateTimeField(auto_now=True)
|
when = models.DateTimeField(auto_now=True)
|
||||||
|
@ -11,6 +11,7 @@ class StockItemSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
model = StockItem
|
model = StockItem
|
||||||
fields = ('url',
|
fields = ('url',
|
||||||
'part',
|
'part',
|
||||||
|
'supplier_part',
|
||||||
'location',
|
'location',
|
||||||
'quantity',
|
'quantity',
|
||||||
'status',
|
'status',
|
||||||
@ -41,5 +42,4 @@ class StockTrackingSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
fields = ('url',
|
fields = ('url',
|
||||||
'item',
|
'item',
|
||||||
'quantity',
|
'quantity',
|
||||||
'pending',
|
|
||||||
'when')
|
'when')
|
||||||
|
@ -29,8 +29,6 @@ class StockDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
class StockFilter(FilterSet):
|
class StockFilter(FilterSet):
|
||||||
min_stock = NumberFilter(name='quantity', lookup_expr='gte')
|
min_stock = NumberFilter(name='quantity', lookup_expr='gte')
|
||||||
max_stock = NumberFilter(name='quantity', lookup_expr='lte')
|
max_stock = NumberFilter(name='quantity', lookup_expr='lte')
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
location = NumberFilter(name='location', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StockItem
|
model = StockItem
|
||||||
@ -76,8 +74,6 @@ class LocationDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
class StockLocationFilter(FilterSet):
|
class StockLocationFilter(FilterSet):
|
||||||
|
|
||||||
parent = NumberFilter(name='parent', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StockLocation
|
model = StockLocation
|
||||||
fields = ['parent']
|
fields = ['parent']
|
||||||
@ -123,8 +119,6 @@ class StockTrackingDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
class StockTrackingFilter(FilterSet):
|
class StockTrackingFilter(FilterSet):
|
||||||
|
|
||||||
item = NumberFilter(name='item', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = StockTracking
|
model = StockTracking
|
||||||
fields = ['item']
|
fields = ['item']
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.core.validators import MinValueValidator
|
||||||
|
|
||||||
from InvenTree.models import Company
|
from InvenTree.models import Company
|
||||||
from part.models import Part
|
from part.models import Part
|
||||||
@ -54,10 +55,10 @@ class SupplierPart(models.Model):
|
|||||||
packaging = models.CharField(max_length=50, blank=True)
|
packaging = models.CharField(max_length=50, blank=True)
|
||||||
|
|
||||||
# multiple that the part is provided in
|
# multiple that the part is provided in
|
||||||
multiple = models.PositiveIntegerField(default=1)
|
multiple = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
# Mimumum number required to order
|
# Mimumum number required to order
|
||||||
minimum = models.PositiveIntegerField(default=1)
|
minimum = models.PositiveIntegerField(default=1, validators=[MinValueValidator(0)])
|
||||||
|
|
||||||
# lead time for parts that cannot be delivered immediately
|
# lead time for parts that cannot be delivered immediately
|
||||||
lead_time = models.DurationField(blank=True, null=True)
|
lead_time = models.DurationField(blank=True, null=True)
|
||||||
@ -75,7 +76,7 @@ class SupplierPriceBreak(models.Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='price_breaks')
|
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='price_breaks')
|
||||||
quantity = models.PositiveIntegerField()
|
quantity = models.PositiveIntegerField(validators=[MinValueValidator(0)])
|
||||||
cost = models.DecimalField(max_digits=10, decimal_places=3)
|
cost = models.DecimalField(max_digits=10, decimal_places=3)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
||||||
from django_filters import NumberFilter
|
|
||||||
|
|
||||||
from rest_framework import generics, permissions
|
from rest_framework import generics, permissions
|
||||||
|
|
||||||
@ -138,12 +137,6 @@ class SupplierPartDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
class SupplierPartFilter(FilterSet):
|
class SupplierPartFilter(FilterSet):
|
||||||
|
|
||||||
supplier = NumberFilter(name='supplier', lookup_expr='exact')
|
|
||||||
|
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
|
|
||||||
manufacturer = NumberFilter(name='manufacturer', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SupplierPart
|
model = SupplierPart
|
||||||
fields = ['supplier', 'part', 'manufacturer']
|
fields = ['supplier', 'part', 'manufacturer']
|
||||||
@ -190,8 +183,6 @@ class SupplierPriceBreakDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
class PriceBreakFilter(FilterSet):
|
class PriceBreakFilter(FilterSet):
|
||||||
|
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SupplierPriceBreak
|
model = SupplierPriceBreak
|
||||||
fields = ['part']
|
fields = ['part']
|
||||||
|
@ -5,8 +5,6 @@ from .models import UniquePart, PartTrackingInfo
|
|||||||
|
|
||||||
class UniquePartSerializer(serializers.HyperlinkedModelSerializer):
|
class UniquePartSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
|
||||||
tracking_info = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UniquePart
|
model = UniquePart
|
||||||
fields = ['url',
|
fields = ['url',
|
||||||
@ -15,8 +13,7 @@ class UniquePartSerializer(serializers.HyperlinkedModelSerializer):
|
|||||||
'serial',
|
'serial',
|
||||||
# 'createdBy',
|
# 'createdBy',
|
||||||
'customer',
|
'customer',
|
||||||
'status',
|
'status']
|
||||||
'tracking_info']
|
|
||||||
|
|
||||||
|
|
||||||
class PartTrackingInfoSerializer(serializers.HyperlinkedModelSerializer):
|
class PartTrackingInfoSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
@ -31,10 +31,6 @@ class UniquePartFilter(FilterSet):
|
|||||||
min_sn = NumberFilter(name='serial', lookup_expr='gte')
|
min_sn = NumberFilter(name='serial', lookup_expr='gte')
|
||||||
max_sn = NumberFilter(name='serial', lookup_expr='lte')
|
max_sn = NumberFilter(name='serial', lookup_expr='lte')
|
||||||
|
|
||||||
sn = NumberFilter(name='serial', lookup_expr='exact')
|
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
customer = NumberFilter(name='customer', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UniquePart
|
model = UniquePart
|
||||||
fields = ['serial', 'part', 'customer']
|
fields = ['serial', 'part', 'customer']
|
||||||
@ -77,7 +73,6 @@ class PartTrackingDetail(generics.RetrieveUpdateDestroyAPIView):
|
|||||||
|
|
||||||
|
|
||||||
class PartTrackingFilter(FilterSet):
|
class PartTrackingFilter(FilterSet):
|
||||||
part = NumberFilter(name='part', lookup_expr='exact')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PartTrackingInfo
|
model = PartTrackingInfo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user