InvenTree/InvenTree/stock/forms.py

238 lines
6.5 KiB
Python
Raw Normal View History

2019-04-27 12:49:16 +00:00
"""
Django Forms for interacting with Stock app
"""
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django import forms
from django.forms.utils import ErrorDict
from django.utils.translation import ugettext as _
from crispy_forms.layout import Field, Layout
from crispy_forms.bootstrap import PrependedText
2019-09-17 10:15:50 +00:00
from mptt.fields import TreeNodeChoiceField
from InvenTree.helpers import GetExportFormats
from InvenTree.forms import HelperForm
from InvenTree.fields import RoundingDecimalFormField
from .models import StockLocation, StockItem, StockItemTracking, StockItemAttachment
class EditStockItemAttachmentForm(HelperForm):
"""
Form for creating / editing a StockItemAttachment object
"""
class Meta:
model = StockItemAttachment
fields = [
'stock_item',
'attachment',
'comment'
]
2018-04-17 13:56:25 +00:00
2018-04-29 14:59:36 +00:00
class EditStockLocationForm(HelperForm):
2019-04-27 12:49:16 +00:00
""" Form for editing a StockLocation """
class Meta:
model = StockLocation
fields = [
'name',
'parent',
'description'
]
2018-04-29 14:59:36 +00:00
class CreateStockItemForm(HelperForm):
2019-04-27 12:49:16 +00:00
""" Form for creating a new StockItem """
serial_numbers = forms.CharField(label='Serial numbers', required=False, help_text=_('Enter unique serial numbers (or leave blank)'))
2020-05-16 01:55:10 +00:00
def __init__(self, *args, **kwargs):
self.field_prefix = {
'serial_numbers': 'fa-hashtag',
'link': 'fa-link',
}
super().__init__(*args, **kwargs)
class Meta:
model = StockItem
fields = [
'part',
'supplier_part',
'location',
'quantity',
'batch',
'serial_numbers',
'link',
'delete_on_deplete',
'status',
2018-04-15 15:02:17 +00:00
]
2018-04-29 14:59:36 +00:00
# Custom clean to prevent complex StockItem.clean() logic from running (yet)
def full_clean(self):
self._errors = ErrorDict()
if not self.is_bound: # Stop further processing.
return
self.cleaned_data = {}
2020-05-16 01:55:10 +00:00
# If the form is permitted to be empty, and none of the form data has
# changed from the initial data, short circuit any validation.
if self.empty_permitted and not self.has_changed():
return
# Don't run _post_clean() as this will run StockItem.clean()
self._clean_fields()
self._clean_form()
2018-04-29 14:59:36 +00:00
class SerializeStockForm(HelperForm):
""" Form for serializing a StockItem. """
2019-09-17 10:19:05 +00:00
destination = TreeNodeChoiceField(queryset=StockLocation.objects.all(), label='Destination', required=True, help_text='Destination for serialized stock (by default, will remain in current location)')
2019-08-28 21:37:44 +00:00
serial_numbers = forms.CharField(label='Serial numbers', required=True, help_text='Unique serial numbers (must match quantity)')
2019-09-17 10:19:05 +00:00
2019-08-28 12:04:04 +00:00
note = forms.CharField(label='Notes', required=False, help_text='Add transaction note (optional)')
quantity = RoundingDecimalFormField(max_digits=10, decimal_places=5)
def __init__(self, *args, **kwargs):
# Extract the stock item
2020-05-16 01:55:10 +00:00
item = kwargs.pop('item', None)
if item:
2020-05-16 01:55:10 +00:00
# Pre-calculate what the serial numbers should be!
2020-05-16 02:03:18 +00:00
sn = item.part.getNextSerialNumber()
2020-05-16 01:55:10 +00:00
if item.quantity >= 2:
sn = "{n}-{m}".format(n=sn, m=int(sn+item.quantity-1))
else:
sn = str(sn)
self.field_placeholder = {
'serial_numbers': sn
}
self.field_prefix = {
'serial_numbers': 'fa-hashtag',
}
super().__init__(*args, **kwargs)
class Meta:
model = StockItem
fields = [
'quantity',
'serial_numbers',
'destination',
'note',
]
class ExportOptionsForm(HelperForm):
""" Form for selecting stock export options """
file_format = forms.ChoiceField(label=_('File Format'), help_text=_('Select output file format'))
include_sublocations = forms.BooleanField(required=False, initial=True, help_text=_("Include stock items in sub locations"))
class Meta:
model = StockLocation
fields = [
'file_format',
'include_sublocations',
]
def get_format_choices(self):
""" File format choices """
choices = [(x, x.upper()) for x in GetExportFormats()]
return choices
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['file_format'].choices = self.get_format_choices()
class AdjustStockForm(forms.ModelForm):
""" Form for performing simple stock adjustments.
- Add stock
- Remove stock
- Count stock
- Move stock
This form is used for managing stock adjuments for single or multiple stock items.
"""
2019-09-17 10:15:50 +00:00
destination = TreeNodeChoiceField(queryset=StockLocation.objects.all(), label='Destination', required=True, help_text=_('Destination stock location'))
2019-04-12 14:52:26 +00:00
note = forms.CharField(label='Notes', required=True, help_text='Add note (required)')
2019-09-17 10:15:50 +00:00
# transaction = forms.BooleanField(required=False, initial=False, label='Create Transaction', help_text='Create a stock transaction for these parts')
2019-09-17 10:15:50 +00:00
confirm = forms.BooleanField(required=False, initial=False, label='Confirm stock adjustment', help_text=_('Confirm movement of stock items'))
set_loc = forms.BooleanField(required=False, initial=False, label='Set Default Location', help_text=_('Set the destination as the default location for selected parts'))
2018-04-29 14:59:36 +00:00
class Meta:
model = StockItem
fields = [
2019-06-02 01:00:28 +00:00
'destination',
'note',
# 'transaction',
'confirm',
2018-04-29 14:59:36 +00:00
]
class EditStockItemForm(HelperForm):
2019-05-09 08:38:37 +00:00
""" Form for editing a StockItem object.
Note that not all fields can be edited here (even if they can be specified during creation.
location - Must be updated in a 'move' transaction
quantity - Must be updated in a 'stocktake' transaction
part - Cannot be edited after creation
"""
2018-04-29 14:59:36 +00:00
class Meta:
model = StockItem
fields = [
'supplier_part',
'serial',
2018-04-29 14:59:36 +00:00
'batch',
'status',
'link',
'delete_on_deplete',
2019-04-13 23:23:24 +00:00
]
class TrackingEntryForm(HelperForm):
""" Form for creating / editing a StockItemTracking object.
"""
class Meta:
model = StockItemTracking
fields = [
'title',
'notes',
'link',
]