feature/#26_enhance_storage_stock_display #37
@ -101,7 +101,8 @@ class ChangeStorageForm(forms.Form):
|
|||||||
foreign_model=get_user_model(),
|
foreign_model=get_user_model(),
|
||||||
prepend='@')
|
prepend='@')
|
||||||
|
|
||||||
is_template = forms.BooleanField(label='is_template', required=False)
|
expand_sub_storage_stocks = forms.BooleanField(label='Expand sub storage Stocks', required=False)
|
||||||
|
is_template = forms.BooleanField(label='Is template', required=False)
|
||||||
|
|
||||||
class AddSubStorageForm(ChangeStorageForm):
|
class AddSubStorageForm(ChangeStorageForm):
|
||||||
template = AutocompleteForeingKeyField(api_search_url='storage-template-list',
|
template = AutocompleteForeingKeyField(api_search_url='storage-template-list',
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.3 on 2025-01-25 13:20
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('parts', '0012_storage_verbose_name'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='storage',
|
||||||
|
name='expand_sub_storage_stocks',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
@ -65,6 +65,7 @@ class Storage(models.Model):
|
|||||||
verbose_name = models.CharField(max_length=100, null=True, blank=True)
|
verbose_name = models.CharField(max_length=100, null=True, blank=True)
|
||||||
parent_storage = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
|
parent_storage = models.ForeignKey('self', on_delete=models.CASCADE, blank=True, null=True)
|
||||||
responsible = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, blank=True, null=True)
|
responsible = models.ForeignKey(get_user_model(), on_delete=models.SET_NULL, blank=True, null=True)
|
||||||
|
expand_sub_storage_stocks = models.BooleanField(default=False)
|
||||||
|
|
||||||
# allow storages to be templates which can be selected when adding new storages
|
# allow storages to be templates which can be selected when adding new storages
|
||||||
is_template = models.BooleanField(default=False)
|
is_template = models.BooleanField(default=False)
|
||||||
@ -106,6 +107,13 @@ class Storage(models.Model):
|
|||||||
else:
|
else:
|
||||||
return self.storage_set.all()
|
return self.storage_set.all()
|
||||||
|
|
||||||
|
def get_tree(self):
|
||||||
|
self.sub_storages = list(self.storage_set.all())
|
||||||
|
for storage in self.sub_storages:
|
||||||
|
self.sub_storages += storage.get_tree()
|
||||||
|
|
||||||
|
return self.sub_storages
|
||||||
|
|
||||||
def validate_unique(self, exclude=None):
|
def validate_unique(self, exclude=None):
|
||||||
if Storage.objects.exclude(id=self.id).filter(name=self.name, parent_storage__isnull=True).exists():
|
if Storage.objects.exclude(id=self.id).filter(name=self.name, parent_storage__isnull=True).exists():
|
||||||
if self.parent_storage is None:
|
if self.parent_storage is None:
|
||||||
@ -407,5 +415,6 @@ def auto_apply_template_structure(sender, instance, created, **kwargs):
|
|||||||
Storage.objects.create(name=sub_storage.name,
|
Storage.objects.create(name=sub_storage.name,
|
||||||
parent_storage=instance,
|
parent_storage=instance,
|
||||||
responsible=instance.responsible,
|
responsible=instance.responsible,
|
||||||
|
expand_sub_storage_stocks=instance.expand_sub_storage_stocks,
|
||||||
is_template=False,
|
is_template=False,
|
||||||
template=sub_storage)
|
template=sub_storage)
|
||||||
|
@ -74,7 +74,13 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView):
|
|||||||
return crumbs
|
return crumbs
|
||||||
|
|
||||||
def search_stock_queryset(self, search):
|
def search_stock_queryset(self, search):
|
||||||
stocks_in_storage = Stock.objects.filter(storage=self.object).order_by(Lower('component__name'))
|
|
||||||
|
if self.object.expand_sub_storage_stocks:
|
||||||
|
stocks_in_storage = Stock.objects.filter(storage__in=self.object.get_tree())
|
||||||
|
else:
|
||||||
|
stocks_in_storage = Stock.objects.filter(storage=self.object)
|
||||||
|
|
||||||
|
stocks_in_storage = stocks_in_storage.order_by(Lower('component__name'))
|
||||||
|
|
||||||
if search is None or search == '':
|
if search is None or search == '':
|
||||||
return stocks_in_storage
|
return stocks_in_storage
|
||||||
@ -139,6 +145,7 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView):
|
|||||||
verbose_name=f.cleaned_data.get('verbose_name'),
|
verbose_name=f.cleaned_data.get('verbose_name'),
|
||||||
parent_storage=self.object,
|
parent_storage=self.object,
|
||||||
responsible=f.cleaned_data['responsible'],
|
responsible=f.cleaned_data['responsible'],
|
||||||
|
expand_sub_storage_stocks=f.cleaned_data['expand_sub_storage_stocks'],
|
||||||
is_template=f.cleaned_data['is_template'],
|
is_template=f.cleaned_data['is_template'],
|
||||||
template=f.cleaned_data.get('template'))
|
template=f.cleaned_data.get('template'))
|
||||||
except ValidationError as v_err:
|
except ValidationError as v_err:
|
||||||
@ -154,6 +161,7 @@ class StockViewDetail(LoginRequiredMixin, BaseTemplateMixin, DetailView):
|
|||||||
self.object.name = f.cleaned_data['storage_name']
|
self.object.name = f.cleaned_data['storage_name']
|
||||||
self.object.verbose_name = f.cleaned_data.get('verbose_name')
|
self.object.verbose_name = f.cleaned_data.get('verbose_name')
|
||||||
self.object.responsible = f.cleaned_data['responsible']
|
self.object.responsible = f.cleaned_data['responsible']
|
||||||
|
self.object.expand_sub_storage_stocks = f.cleaned_data['expand_sub_storage_stocks']
|
||||||
self.object.is_template = f.cleaned_data['is_template']
|
self.object.is_template = f.cleaned_data['is_template']
|
||||||
self.object.save()
|
self.object.save()
|
||||||
except ValidationError as v_err:
|
except ValidationError as v_err:
|
||||||
|
Loading…
Reference in New Issue
Block a user